Important note when updating LINQ-to-SQL view fields

Filed in Software Developement Leave a comment

I am working on a complex project right now where I am using LINQ-to-SQL with some complicated views. I need to at some times updates some of the fields on these views. I know this is possible because you can achieve this in SSMS (note that you can only update fields which already exist, NULL outer join fields will not update since they don’t actually exist). Anyways, I would get my row via the view from the data context, then update the property corresponding to the field. But when I called SubmitChanges() nothing would happen, the database would not be updated.  So to debug I would attach the data context logger to Console.Out so I could visualize why it wasn’t working. The log was empty on the SubmitChanges() call, which was troubling.

The solution to this problem is to make sure your views have a Primary Key field set. By default your views won’t have this property set because it’s ambiguous on a view. But you can specify this in the property editor when the field is highlighted. If your view doesn’t have the equivalent of a primary key then you are SOL because you cannot update a view field without a PK.  Once I specified the PK on the view, the updates started working.

This behaviour, while it make perfect sense, is simply not obvious and very difficult to track down if you don’t realize what the problem is. It’s too bad there isn’t some sort of warning from LINQ-to-SQL when you generate a view with no PK field set.  Anyways, simple solution to an otherwise difficult to track down problem.

, , , ,

AsyncTask in MonoDroid the .NET way (Task Parallel Library)

Filed in Software Developement 2 Comments

I was looking into how to implement an async task in android last night, specifically to download some content from the web in the background.  Obviously, I was interested in using mono for android, so I started off by created a new ICS project and started researching AsyncTask<T1, T2, T3> which is what I had remembered looking into a while back.  It didn’t take long before I realized that this strategy was not the direction I wanted to go. My main problem with the AsyncTask framework is that you must extend the class for each specific type of task you want to perform. You can param it with generics, but really I just hate cluttering the project with all these extended classes (I’m not on that java bandwagon, even a little).

I wondered how .NET did this natively. I know that in the past I have usually just used the ThreadPool and sometimes the BackgroundWorker (though very rarely).  But I figured by 4.0 .NET must have come up with a decent solution for async task management. The answer is the Task Parallel Library (or TPL).  Even more interesting is the new async task framework (in .NET 4.5) but I will wait until the new visual studio is RTM before I jump on that.

TPL has a lot of features that I consider very useful, the biggest being that it’s agnostic to your task and that it supports hierarchical task control.  Tasks are defined using delegates (lambda’s) and you can combine any number of tasks into simple or complex hierarchies that will execute according to your needs.  The only downside to TPL is the lack of native progress reporting, though the work around to this is so easy it’s hardly a downfall.

I wrote a (VERY) simple monodroid app to showcase how to leverage the TPL.  This demo simply starts a progress counter on a background task, updates the UI with regular progress updates, and allows immediate cancellation of the task.  The primary task also includes a continuation task that would perform task clean up.

using System;
using System.Threading;
using System.Threading.Tasks;
using System.Linq;

using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;

namespace AsyncTaskTest
{
    [Activity(Label = "AsyncTaskTest", MainLauncher = true, Icon = "@drawable/icon")]
    public class Activity1 : Activity
    {
        private TaskScheduler Scheduler { get; set; }
        private CancellationTokenSource Cancel { get; set; }
        private Task<int> ProgressTask { get; set; }

        private Button Button { get; set; }

        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);

            SetContentView(Resource.Layout.Main);

            Button = FindViewById<Button>(Resource.Id.MyButton);
            Scheduler = TaskScheduler.FromCurrentSynchronizationContext();
        }

        protected override void OnResume()
        {
            base.OnResume();

            Button.Click += ButtonClicked;
        }

        protected override void OnPause()
        {
            base.OnPause();

            Button.Click -= ButtonClicked;
            Cancel.Cancel();
        }

        private void ButtonClicked(object sender, EventArgs e)
        {
            if (ProgressTask == null || ProgressTask.Status == TaskStatus.RanToCompletion)
            {
                ProgressTask = CreateTask(1000);
                ProgressTask.Start();
            }
            else
            {
                Button.Text = "Cancelling...";
                Cancel.Cancel();
                ProgressTask.Wait();
                int val = ProgressTask.Result;
                ProgressTask = null;
                Button.Text = string.Format("Cancelled at {0,3}%", val);
            }
        }

        private Task<int> CreateTask(int count)
        {
            Cancel = new CancellationTokenSource();
            var task = new Task<int>(() =>
            {
                var progress = 0;

                foreach (var i in Enumerable.Range(1, count))
                {
                    if (Cancel.IsCancellationRequested)
                    {
                        return progress;
                    }

                    progress = i * 100 / count;

                    Task.Factory.StartNew(() =>
                    {
                        Button.Text = string.Format("{0,3}%", progress);
                    }, Cancel.Token, TaskCreationOptions.None, Scheduler);

                    Thread.Sleep(10);
                }

                return 100;
            }, Cancel.Token, TaskCreationOptions.None);

            task.ContinueWith(_ =>
            {
                Button.Text = "100% DONE";
            }, Cancel.Token, TaskContinuationOptions.None, Scheduler);

            return task;
        }
    }
}

As you can see, the lack of native progress reporting is replaced simply by a new temporary task that’s started with the UI scheduler. By using the scheduler like I have, you can perform UI operations in the middle of a background task, without making the thread context complain about access.  I like the simplicity of this TPL, but I really cannot wait to get into .NET 4.5 with the new async task framework, things will be even simpler and cleaner.

if you want to try out this demo code, just create a new mono for android application in visual studio, and replace the Activity1.cs source code with the source code above. I tried to keep the demo code as simple as possible so I was really only showcasing what the TPL could do in monodroid.

, , , , ,

TOP