Strategy Pattern and Delegate

Strategy Pattern will encapsulate a family of algorithm and make them interchangeable. So we can define the unified interface for the algorithm. It represents the polymorphism of OOD. For instance, we will develop a tool to calculate the tax. Assumed that the tax is divided into the personal income tax and enterprise tax. We can apply the Strategy Pattern into it and abstract the calculation of tax into the interface ITaxStrategy:

public interface ITaxStrategy

{

    double Calculate(double income);

}

 

The concrete tax strategies will implement the ITaxStrategy interface:

public class PeronalTaxStrategy : ITaxStrategy

{

    public double Calculate(double income)

    {

        //Implementation

    }

}

public class EnterpriseTaxStrategy : ITaxStrategy

{

    public double Calculate(double income)

    {

        //Implementation

    }

}

 

At the same time, we will define the utility class to provide the clients with convenient.

public class TaxOp

{

    private ITaxStrategy strategy;

    public TaxOp(ITaxStrategy strategy)

    {

        this.strategy = strategy;

    }

    public double GetTax(double income)

    {

        return strategy.Calculate(income);

    }

}

Now, the clients can invoke the related operation of TaxOp class to get the tax according to concrete strategy object which is passed as parameter of constructor.

public class App

{

    public static void Main(string[] args)

    {

        TaxOp op = new TaxOp(new PersonalTaxStrategy());

        Console.WriteLine(“The Personal Tax is :{0}”, op.GetTax(1000));

    }

}

 

It follows the idea of OOD. However, we can make use of the delegate syntax in C# for some simple algorithms. It will simplify our implementation. Maybe it will violate the idea of OOD, but it provides the extensibility also.

 

For the same example given before, we can modify the interface to delagate type:

public delegate double CalculateTax(double income);

 

Of course, we should provide the different implemenation:

public class Tax

{

    public static double CalculatePersonalTax(double income)

    {

        //Implementation

    }

    public static double CalculateEnterpriseTax(double income)

    {

        //Implementation

    }

}

 

Accordingly, we must modify the TaxOp Class:

public class TaxOp

{

    private CalculateTax calDel;

    public TaxOp(Calculate calDel)

    {

        this.calDel = calDel;

    }

    public double GetTax(double income)

    {

        return calDel(income);

    }

}

 

And the implementation of Clients program:

public class App

{

    public static void Main(string[] args)

    {

        TaxOp op = new TaxOp(new CalculateTax(Tax.CalculatePersonalTax));

        Console.WriteLine(“The Personal Tax is :{0}”, op.GetTax(1000));

    }

}

 

Two solutions are more or less the same. The code snippet is also similar. But the idea based on the essence of design is different completely. It’s the difference between OO and OP. The former encapsulates the behavior in an object; the latter handles the method directly, and uses the delegate to provide the extensibility. In fact, the delegate represents the feature of Functional Programming nearly. It seams like a pointer to the function in C++. In other words, the delegate is another ways of abstraction. It is more flexible than interface type. After C# 2.0 introduced the anonymous method, and C# 3.0 introduced the Lambda expression, delegate becomes more and more useful and popular on C# programming. Before C# 2.0, I prefer to interface; now I prefer to delegate. Even we may use the delegate type to provide the brand new implementation of some design patterns such as Strategy Pattern, Command Pattern etc.

Advertisements

Using Extension Methods to Verify the Method Calling

Using the extension method provided by C# 3.0 as the new feature, you can add the new methods for the compiled assembly to meet the need of extensible. In addition to this, extension method can also be effective to reduce duplicate code and improve the reusability of system if you are able to combine the generic and type inference. For example, the method like this:

public class CustomerDAL

{

    public IEnumerable<Customer> FindCustomers(string roleName)

    {

        return from customer

            in context.Customer

               where customer.RoleName.Equals(roleName)

               select customer;

    }

}

It will throw the NullReferenceException if you invoke it by this way as below when it returns null:

Customer customer = new CustomerDAL().FindCustomers(Role.Admin).First();

So we have to verify the result. If it is null, the custom exception should be thrown:

public IEnumerable<Customer> FindCustomers(string roleName)

{

    IEnumerable<Customer> customers = from customer

            in context.Customer

            where customer.RoleName.Equals(roleName)

            select customer;

    if (customers == null)

    {

        throw new MyException(“Cann’t find the customers.”);

    }

    return customers;

}

 

The logic of verification implemetation will spread through the everywhere in the system if there are too many methods which need to be verified. It is difficult to reuse these code, and it is bad smell absolutely.

Craig Andera post the blog to solve this problem. He wrote:
A NullReferenceException would be thrown, but we wanted something more specific. So we came up with this:

public static T OrThrow<T>(this T obj, Exception e) {

    if (obj == null) {

        throw e;

    }

    return obj;

}

 

Using the OrThrow() method, the invoking way might be changed like this:

Customer customer = new CustomerDAL().

    FindCustomers(Role.Admin).OrThrow

    (new MyException(“Can’t find Customer”)).First();

 

Craig continues to say:
the OrThrow extension method is generic on the type it’s invoked on, and it returns that type, so you can insert it into a chained expression and you don’t lose any intellisense. And because of type inference, you don’t actually have to specify the type, which cleans up the expression a bit.

That is, OrThrow() method can be applied to any type. Following this idea, we can create an instance as default value to avoid to throw the NullReferenceException using the extension method:

public static T Instance<T>(this T obj) where T:new()

{

    if (obj == null)

    {

        obj = new T();

    }

    return obj;

}

 

Due to type parameter T need to create an instance, we must add the constraint with new(). So that we can’t use the Instance<T> extension method for abstract type or interface type such as IEnumerable. But it is effective to method like this:

public class ListObject

{

    public List<string> Foo()

    {

        return null;

    }

}

 

Through by using Instance() method, we can invoke the related properties and methods of List instance safely. For example, we can use the Count property as below:

Console.WriteLine(new ListObject().Foo().Instance().Count);

 

The result value is 0. If Instance() method is not used, the NullReferenceException should be thrown.

How to know Transaction Is Successful

Based on .Net Framework, it is convient to use transaction with System.Transactions.TransactionScope class. If no error occurs in the transaction scope, the TransactionScope object will complet, otherwise rollback.

In some situations, we need execute some business logics after transaction complet successfully. Note that we don’t add some business logic code lines after complet() method. In another word, we must place these business logics out of the transaction scope. However, the transaction object had been disposed out of using statement. So, how to know the transaction is successful?

Transaction object exposes the event called TransactionCompleted and provides TransactionStatus which is enumeration type. TransactionStatus enumeration type includes four values: Aborted, Committed, Active and InDoubt. Then we can make a decision depending on the value of TransactionStatus which is belong to TransactionInformation object. TransactionInformation object is a property of Transaction instance.

The sample code is as below: 

using (TransactionScope ts = new TransactionScope())

{

    Transaction transaction = Transaction.Current;

    transaction.TransactionCompleted += pro.OnCompleted;

    pro.UpdateEmployee();

    pro.DeleteCustomer();

    ts.Complete();           

}

 

void OnCompleted(object sender, TransactionEventArgs e)

{

    Debug.Assert(sender.GetType() == typeof(Transaction));

    Debug.Assert(object.ReferenceEquals(sender,e.Transaction));

    Transaction transaction = e.Transaction;

    switch (transaction.TransactionInformation.Status)

    {

        case TransactionStatus.Aborted:

            m_TransactionCommitted = false;

            //Not to do something when failed

            break;

        case TransactionStatus.Committed:

            m_TransactionCommitted = true;

            //do something when success

            break;

        default:

            m_TransactionCommitted = false;

            break;

    }

}

A Little Bit Regret for Generic in C#

In our project, I defined the ThrowHelper helper class to help us throw the customized exception. For instance, I defined a exception as below:

public class EmployeeException : ApplicationException

{

    public EmployeeException()

        : base()

    { }

 

    public EmployeeException(string message)

        : base(message)

    { }

 

    public EmployeeException(string message, Exception innerException)

        : base(message, innerException)

    { }

}

 

Then we might define the method to throw it to be invoked by other developer conveniently:

public static class ThrowHelper

{

    public static EmployeeException ThrowEmployeeException(string message)

    {

        LogService.Error(message);

        throw new EmployeeException(message);

    }

 

    public static EmployeeException ThrowEmployeeException(string message, Exception innerException)

    {

        LogService.Error(message, innerException);

        throw new EmployeeException(message, innerException);

    }

}

 

The problem is that we need to add the method such as before if we defined a number of customized exceptions. It’s tedious. The developer must dislike this way whenever.

Can we use the generic type to solve this problem? For example, we may define a new version method using generic type as below:

public static class ThrowHelperGeneric<TCustomException>

    where TCustomException : ApplicationException, new()

{

    public static TCustomException ThrowCustomException(string message)

    {

        LogService.Error(message);

        throw new TCustomException(message);

    }

 

    public static TCustomException ThrowCustomException(string message, Exception innerException)

    {

        LogService.Error(message, innerException);

        throw new TCustomException(message, innerException);

    }

}

 

Opps, it’s regretful. It can’t support to invoke constructor with parameter based on .Net framework. We have to use the reflection technology to solve it:

public static class ThrowHelperGeneric<TCustomException>

    where TCustomException : ApplicationException, new()

{

    public static TCustomException ThrowCustomException(string message)

    {

        LogService.Error(message);

        TCustomException exception = (TCustomException)typeof(TCustomException).GetConstructor(new Type[] { typeof(string) }).

            Invoke(new object[] { message });

 

        throw exception;

    }

 

    public static TCustomException ThrowCustomException(string message, Exception innerException)

    {

        LogService.Error(message, innerException);

        TCustomException exception = (TCustomException)typeof(TCustomException).GetConstructor(new Type[] { typeof(string), typeof(Exception) }).

            Invoke(new object[] { message, innerException });

 

        throw exception;

    }

}

 

It’s a terrible choice. I don’t like to do in this way. Even though we can use new() in the where constraint, how come Microsoft can’t provide the similiar operator or keyword in the where constraint to constrain the type of the parameter in the constructor? Like this:

public static class ThrowHelperGeneric<TCustomException>

    where TCustomException : ApplicationException, new(), new(string), new(string, Exception)

{

    public static TCustomException ThrowCustomException(string message)

    {

        LogService.Error(message);

        throw new TCustomException(message);

    }

 

    public static TCustomException ThrowCustomException(string message, Exception innerException)

    {

        LogService.Error(message, innerException);

        throw new TCustomException(message, innerException);

    }

}

I don’t know whether it will support this function in the furture version with C#. Is it too difficult?

Programming Standard for Our Team

1. Exception Handling
1) Deprive all custom exceptions from System.ApplicationException, and putting all custom exceptions into WD.AIATools.Common.Exceptions namespace;
2) Define three overloaded version for constructor, such as:

public class ActionParamsException : ApplicationException

{

    public ActionParamsException()

        : base()

    {    }

 

    public ActionParamsException(string message)

        : base(message)

    {    }

 

    public ActionParamsException(string message, Exception ex)

        : base(message, ex)

    {    }

}

3) Provide a helper method which includes the logging operation for your custom exception in ThrowHelper class:

    public static ActionParamsException ThrowActionParamsException(string message, Exception ex)

    {

        LogService.Error(message, ex);

        return new ActionParamsException(message, ex);

    }

4) In Data Access Layer, try to catch the exception which is thrown by .NET Framework, and re-throw the custom exception by invoking the helper method with ThrowHelper. For example:

        try

        {

            Foo();

        }

        catch (SqlException ex)

        {

            throw; //Avoid

            ThrowHelper.ThrowCustomException(“message”, ex); //OK

        }

        catch (NotSupportedException ex)

        {

            ThrowHelper.ThrowCustomException(“message”, ex); //OK

        }

        catch (Exception ex)

        {

            ThrowHelper.ThrowCustomException(“message”, ex); //OK

        }

        finally //if necessary

        {

            //do something

        }

5) Don’t catch the exception in Business Logic Layer otherwise it is necessary.
6) In Presentation Layer, it includes two cases:
a) Show the error information on the current page through by catching the exception;
b) Link to the error page which includes the error information with Exception.Message;
7) Don’t catch the exception inside for or foreach statement.

 

2. Robust Check Policy
1) Avoid throwing the NullReferenceException. Check whether the object is null before using it:

if (someObject != null)

{

    //Do something;

}

else //if necessary

{

    //throw the custom exception or else

}

2) Never return the null value especially if the object is collection:

public IList GetSomeList()

{

    //Something to do;

    if (NoItemInCollection)

    {

        return new List(); //OK

        return null; //Avoid;

    }

}

3) Always explicitly initialize an array of reference types using a for loop:

public class MyClass{}

 

const int ArraySize = 10;

MyClass[] array = new MyClass[ArraySize];

for (int index = 0; index < ArraySize; ++index)

{

    Array[index] = new MyClass();

}

4) Prefer to use foreach statement instead of for statement;
5) Try to check what the instance’s type is before casting the reference type by using “is” operator:

if (someObject is Foo)

{

    Foo object = (Foo)someObject;

}

//Or

Foo object = someObject as Foo;

6) Remember to dispose the resource when using the unmanaged resource; Always use a using statement in this situation.

3. Code Practices
1) Avoid putting multiple classes in a single file;
2) Never hard-code a numeric value; always declare a constant instead;
3) Avoid providing explicit values for enums unless they are integer powers of 2:

//Correct

public enum Color

{

    Red, Green, Blue

}

Note: Putting all enum types into the specific file.
4) Use String.Empty instead of “”;
5) When building a long string, use StringBuilder, not String;
6) Always have a default case in a switch statement;

Common Base Class for LINQ to SQL

Language-Integrated Query (LINQ) is a set of features in Visual Studio 2008 that extends powerful query capabilities to the language syntax of C# and Visual Basic. As a part of LINQ, LINQ to SQL provides a run-time architecture for managing relational data as objects. To some extent, it equals to ORM tool or framework such as NHibernate and Castle based on .NET framework. It becomes our preferred choice gradually when we want to access the database.

In LINQ to SQL, all variables in the Data Model of a relational database can be strongly typed which provides the benefit of compile-time validation and IntelliSense. We can fetch the data from the database using query expression (it includes query syntax and method syntax.)

However, the strongly typed feature is not conducive to abstract the common logic of data operations so the developer has to define a specific class to handle the entity object. It results in a large number of repeated codes. If we can implement the base class which encapsulates the common operations such as Select, Where, Add, Update and Delete, it will be useful for N-Tier application.

Fortunately, the generic type will help us to achieve our goal. We can invoke a method called GetTable() in DataContext of LINQ. For example, we can implement the Where method which accepts the Lambda expression to find the result we want to get:

public IList<TEntity> Where(Func<TEntity, bool> predicate)

{

    InitDataContext();

    return m_context.GetTable<TEntity>().Where(predicate).ToList<TEntity>();

}

 

It’s simple. Even, we can expose the method which accepts the condition clause using Dynamic Query:

public static class DynamicQueryable

{

    public static IQueryable<T> Where<T>(this IQueryable<T> source, string predicate, params object[] values)

    {

        return (IQueryable<T>)Where((IQueryable)source, predicate, values);

    }

 

    public static IQueryable Where(this IQueryable source, string predicate, params object[] values)

    {

        if (source == null) throw new ArgumentNullException(“source”);

        if (predicate == null) throw new ArgumentNullException(“predicate”);

        LambdaExpression lambda = DynamicExpression.ParseLambda(source.ElementType, typeof(bool), predicate, values);

        return source.Provider.CreateQuery(

            Expression.Call(

                typeof(Queryable), “Where”,

                new Type[] { source.ElementType },

                source.Expression, Expression.Quote(lambda)));

    } 

}

public IList<TEntity> Where(string predicate, params object[] values)

{

    InitDataContext();

    return m_context.GetTable<TEntity>().Where(predicate, values).ToList<TEntity>();

}

 

Of course, the query function is not a problem because we don’t need the properties of the entity when we invoke these methods and don’t care about the composition of Lambda Expression.

The key issue is how to update or delete the record of data table. You know, we must fetch the entity which is going to be operated before updating or deleting it. The keyword to search is often its identity. Furthermore, Object Identity and Change Tracking in Data Context need the object’s identity to track the changing of it. Usually, we would add the Id column which is identity or Guid for each table. Then we can fetch the entity object according to it:

    public void Update(Employee employee)

    {

        LinqSampleDataContext context = new LinqSampleDataContext();

 

        Employee emp = this.Where(e => e.EmployeeID == employee.EmployeeID);

        emp.FirstName = “First Name”;

        emp.LastName = “Last Name”;

 

        context.SubmitChanges();

    }

 

Obviously, we don’t know the entity’s properties if we use the generic type such as TEntity like above. Without the keyword how do we associate the changes with the existing record? LINQ introduces the Attach method which can attach the changed object to the context. There are three overloaded versions as below:
Attach(Object entity): Attaches an entity to the DataContext in an unmodified state;
Attach(Object entity, bool asModified): Attaches all entities of a collection to the DataContext in either a modified or unmodified state.
Attach(Object entity, Object orginal): Attaches an entity to the DataContext in either a modified or unmodified state by specifying both the entity and its original state.

Attach method is used to associate the deserialized entities to a new instance of a DataContext. However, we can associate the entity in one DataContext to another DataContext by using it. In update or delete case, this method is very useful. For example, we want to update the record according to a changed entity from another DataContext:

    public void Update(TEntity changedEntity)

    {

        InitDataContext();

 

        try

        {

            m_context.GetTable<TEntity>().Attach(changedEntity, true);

            m_context.SubmitChanges();

        }

        catch (ChangeConflictException)

        {

            m_context.ChangeConflicts.ResolveAll(RefreshMode.KeepCurrentValues);

            m_context.SubmitChanges();

        }

    } 

 

It looks good, but not enough. We can’t attach a changed entity unless the entity has a TimeStamp column in the corresponding table. Therefore, we should add a column whose type is TimeStamp in SQL Server 2005, or set the IsVersion property to true for Id property in LINQ to SQL Designer. My advice is to create a TimeStamp column for your datatable, and it will improve the performance because it won’t check all columns whether they are changed during handling concurrency.

In fact, we can pass the original entity with generic type also. The only problem is how to pass the values you want to change. The solution to this problem is using Action delegate. The code snippet is as below:

    public void Update(TEntity originalEntity, Action<TEntity> update)

    {

        InitDataContext();

        try

        {

            m_context.GetTable<TEntity>().Attach(originalEntity);

            update(originalEntity);

 

            m_context.SubmitChanges();

        }

        catch (ChangeConflictException)

        {

            m_context.ChangeConflicts.ResolveAll(RefreshMode.KeepCurrentValues);

            m_context.SubmitChanges();

        }

    } 

 

Now we can invoke it passing Lambda expression like this:

    [TestMethod()]

    public void UpdateWithAction()

    {

        LinqSampleDataContext context = new LinqSampleDataContext();

        EmployeeAccessor accessor = new EmployeeAccessor();

 

        Employee employee = context.Employees.Single(e => e.EmployeeID == 1);

 

        accessor.Update(employee, t => { t.FirstName = “First”; t.LastName = “Last”; });

    }

 

Unfortunately, the test case can’t pass sometimes. It will throw a NotSupportedException. And the message of exception is:
An attempt has been made to Attach or Add an entity that is not new, perhaps having been loaded from another DataContext. This is not supported.

Why? What happens? The real reason is the entity we handle has some associations with other entities. Please see figure 1:

linqbaseclass01

Figure 1 : The entity with association

If you remove all relationships in Employee table, and re-generated the data model, the test case would pass.

What shall we do? Of course, to remove all relationships of table explicitly is not a good way to solve the issue. It will impact on the whole data model and can’t be accepted when we develop the application. I found one guy, Steve Michelotti, raised one solution to solve it. That was to provide one method called Detach to remove the relationships using partial class:

public partial class Contact

{

    public void Detach()

    {

        foreach (Address address in this.Addresses)

        {

            address.Detach();

        }

    }

}

 

public partial class Address

{

    public void Detach()

    {

        this._AddressType = default(EntityRef<AddressType>);

        this._State = default(EntityRef<State>);

    }

 

Good job! But it is not perfect. First, it’s too complex because we must define the Detach method for every entity which has association with others. Second, we can’t abstract it to the base class in this way. In the base class, we don’t know the specific type of TEntity. In this case, we should turn to the reflection technology. It’s my way:

    private void Detach(TEntity entity)

    {

        foreach (FieldInfo fi in entity.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance))

        {

            if (fi.FieldType.ToString().Contains(“EntityRef”))

            {

                var value = fi.GetValue(entity);

                if (value != null)

                {

                    fi.SetValue(entity, null);

                }

            }

            if (fi.FieldType.ToString().Contains(“EntitySet”))

            {

                var value = fi.GetValue(entity);

                if (value != null)

                {

                    MethodInfo mi = value.GetType().GetMethod(“Clear”);

                    if (mi != null)

                    {

                        mi.Invoke(value, null);

                    }

 

                    fi.SetValue(entity, value);

                }

            }

        }

    }

 

For EntityRef fields, we may set their values to null by calling the SetValue of FieldInfo class to remove the relationship. However, we can’t do EntitySet in the same way because it is a collection. If set to null, it will throw exception. So I get the method information of the field and invoke the Clear method to clear all items in this collection. Finally, my implementation of Update method is as below:

    public void Update(TEntity originalEntity, Action<TEntity> update, bool hasRelationship)

    {

        InitDataContext();

        try

        {

            if (hasRelationship)

            {

                //Remove the relationship between the entitis

                Detach(originalEntity);

            }

            m_context.GetTable<TEntity>().Attach(originalEntity);

            update(originalEntity);

 

            m_context.SubmitChanges();

        }

        catch (ChangeConflictException)

        {

            m_context.ChangeConflicts.ResolveAll(RefreshMode.KeepCurrentValues);

            m_context.SubmitChanges();

        }

    }

 

Delete operation is similar except we don’t need invoke the second version of Attach (Attach(object entity, bool asModified)). Here is the code snippet:

    public void Delete(TEntity entity, bool hasRelationship)

    {

        InitDataContext();

        try

        {

            if (hasRelationship)

            {

                //Remove the relationship between the entities;

                Detach(entity);

            }

 

            m_context.GetTable<TEntity>().Attach(entity);

            m_context.GetTable<TEntity>().DeleteOnSubmit(entity);

            m_context.SubmitChanges();

        }

        catch (ChangeConflictException)

        {

            m_context.ChangeConflicts.ResolveAll(RefreshMode.KeepCurrentValues);

            m_context.SubmitChanges();

        }

    }

    public void Delete(IList<TEntity> entities, bool hasRelationship)

    {

        InitDataContext();

        try

        {

            if (hasRelationship)

            {

                //Remove the relationship

                foreach (TEntity entity in entities)

                {

                    Detach(entity);

                }

            }

 

            m_context.GetTable<TEntity>().AttachAll(entities);

            m_context.GetTable<TEntity>().DeleteAllOnSubmit(entities);

 

            m_context.SubmitChanges();

        }

        catch (ChangeConflictException)

        {

            m_context.ChangeConflicts.ResolveAll(RefreshMode.KeepCurrentValues);

            m_context.SubmitChanges();

        }

    } 

 

Don’t worry about the correctness of final result when we remove the relationship between the entities. The Attach method is just responsible for associating the entity to a new instance of DataContext to track the change. When you submit the changes, DataContext will check the real value in the mapping database and update or delete the record according to the passed entity. Especially, you should take an action such as Cascade in the database if you want to cascade delete between foreign key table and primary key table, see figure 2.

linqbaseclass02

Figure 2: Set the delete rule

If no action, the System.Data.SqlClient.SqlException will be thrown and the message of it when you delete the entity as Primary Key table, like this:
The DELETE statement conflicted with the REFERENCE constraint “FK_Orders_Employees”. The conflict occurred in database “Northwind”, table “dbo.Orders”, column ‘EmployeeID’.

Maybe you notice the InitDataContext method is invoked in all methods to access the data. Its implementation like this:

    private TContext m_context = null;

 

    private TContext CreateContext()

    {

        return Activator.CreateInstance<TContext>() as TContext;

    }

 

    private void InitDataContext()

    {

        m_context = CreateContext();

    }

 

Why do we need create a new instance of DataContext for each method? The reason is Caching policy in DataContext. If you create a new instance of DataContext and query the data from the database though by it, then change its value and execute the next query though by the same instance, the DataContext will return the data stored in the internal cache rather than remapping the row to the table. For more information, please refer to the Linq in Action.

So, the best practice is to create a new instance of DataContext for each operation. Don’t worry about the performance, the DataContext is lightweight resource.

Let’s consider about the concurrency issue. The default option is Optimistic Concurrency. When the values are to be saved, the DataContext would check the previous values to see if they have been changed. If conflict occurs, the DataContext would need to know whether to automatically overwrite the previous changes, keep the previous changes, or somehow merge the changes.

The concurrency issue is not within the scope of this article. We can’t say which one of three ways is the best or worst, it depends on the business situation. Usually, I will handle concurrency by the rule of last submit win. So I encapsulate the SubmitChanges method and define it as visual method, if necessary, the subclass may override it:

public class AccessorBase<TEntity, TContext>

    where TEntity : class, new()

    where TContext : DataContext, new()

{

    private TContext m_context = null;

 

    /// <summary>

    /// It provides the default policy to handle the corrency conflict

    /// </summary>

    /// <param name=”context”>Data Context</param>

    protected virtual void SubmitChanges(TContext context)

    {

        try

        {

            context.SubmitChanges(ConflictMode.ContinueOnConflict);

        }

        catch (ChangeConflictException)

        {

            context.ChangeConflicts.ResolveAll(RefreshMode.KeepCurrentValues);

            context.SubmitChanges();

        }

        catch (Exception ex)

        {

            throw ex;

        }

    }

 

    /// <summary>

    /// Update the entity which was passed

    /// The changedEntity cann’t have the relationship between the entities

    /// </summary>

    /// <param name=”originalEntity”>It must be unchanged entity in another data context</param>       

    /// <param name=”update”>It is Action<T>delegate, it can accept Lambda Expression.</param>

    /// <param name=”hasRelationship”>Has relationship between the entities</param>

    public void Update(TEntity originalEntity, Action<TEntity> update, bool hasRelationship)

    {

        InitDataContext();

 

        try

        {

            if (hasRelationship)

            {

                //Remove the relationship between the entitis

                Detach(originalEntity);

            }

 

            m_context.GetTable<TEntity>().Attach(originalEntity);

 

            update(originalEntity);

 

            SubmitChanges(m_context);

        }

        catch (InvalidCastException ex)

        {

            throw ex;

        }

        catch (NotSupportedException ex)

        {

            throw ex;

        }

        catch (Exception ex)

        {

            throw ex;

        }

    }

}

 

Now, we have a common base class which can be derived to handle the entity. For example:

public class EmployeeAccessor : AccessorBase<Employee, NorthwindDataContext>

{

}

 

You don’t need implement any method. It’s more convenient to access the Employee table by using an instance of EmployeeAccessor:

    [TestMethod()]

    public void UpdateEmployee()

    {

        EmployeeAccessor accessor = new EmployeeAccessor();

        IList<Employee> entities = accessor.Where(e => e.EmployeeID == 1);

 

        if (entities != null && entities.Count > 0)

        {

            entities[0].FirstName = “Bruce”;

            entities[0].LastName = “Zhang”;

 

            accessor.Update(entities[0], true, true);

        }

    }

 

You may let Employee entity derive my base class directly even:

public partial class Employee : AccessorBase<Employee, NorthwindDataContext>

{

}

 

Its behavior is very similar with Rich Domain Model like Martin Fowler said in the article which title is Anemic Domain Model.

 

Download Source Code: LinqSample_Src.zip     368KB

 

Note: The database which my sample use is Northwind in SQL Server 2005 and I add a new column which type is TimeStamp for each table.

Select In Sentence with Linq To Sql

Considering the scenario: If I want to look for some records according to the collection of their ID from the data table, how to write the correct LINQ expression? For instance, I create the training plan table in SQL Server 2005. The data structure of this table is as follows:
ID type: bigint
Name type:nvarchar(50)

Notes: the rest columns have been neglected.

Now I have the collection of ID such as IList which contains some items. It will be the in parameter to find the list of TrainingPlan object. If I use the SQL sentence, it will be:

select * from trainingplan where ID in {1, 2, 3, 4}

So how to do to meet the requirement in LINQ? That’s easy, the code snippet like this:

        public IList GetTrainingPlans(IList ids)

        {

            long[] tpIDs = ids.ToArray();

            var query = from tp in context.TrainingPlans

                        where tpIDs.Contains(tp.ID)

                        select tp;

            return query.ToList();

        }

Please note the first line in the method body. Why did I convert ids(IList) to long[] array? When the input params is IList type, and then invoke its Contains() method, It will throw a NotSupportedException. The error information is “Boolean Contains(System.Int64)” has no supported translation to SQL.

But, if it is Array type or List type, it will not. It’s very strange, isn’t it? Yeah, that’s it whichi I am confused. Maybe the big difference is between the class and interface.