Guidelines for working with ADO.Net Entity Framework

I would like to share with you some Guidelines for working with ADO.Net Entity Framework and other Linq flavored Framework.

  • We should enable all the integrity from the database. The validation of the integrity is not provided by the framework. It will be more effective if the database can return the index or the foreign key that is failing. I will need to do some test on this.
  • Don’t add instance properties or methods to the entities. Entities are not like business objects, they are only data container. Also, using instance properties inside entity reduce the easiness to write queries using the linq syntax.

    Ex: Supposed you’ve add the property MyProperty by code to the entity Employee. Now, supposed someone want to query the employee with your property:

    var q = from e in db.Employees
    where e.MyProperty != null
    select e;

    This will throw an exception at runtime because MyProperty cannot be translated to SQL.
  • Consider not putting validation into the model.
  • Don’t put UI stuff in the model. It may seems evident but ...
  • Use an interface over your model. Consider design for testability.

I will probably add more in the future.

Stay tune!

Dany

WeakEventHandler

I came across a problem this week. I was needing a weak delegate to handle a situation where I have a ListBox and I want it to listen to a property changed on a selected ListBoxItem. This situation need to have a weak delegate because if the ListBoxItem is kept referenced, I want to let the ListBox to be garbage collected.

This is how I have implemented the WeakEventHandler. I thought it was a good implementation because it also supports the anonymous methods even if they are closure.

WeakEventHandler

The WeakEventHandler is a thin class inheriting the WeakHandler<T> and provinding a closure delegate in the CreateHandler.

public sealed class WeakEventHandler : WeakHandler<EventHandler>
{
    public WeakEventHandler(EventHandler handler)
        : base(handler)
    {
    }

    protected override EventHandler CreateHandler(WeakReference weakReference)
    {
        return (sender, e) =>
        {
            var h = (EventHandler)weakReference.Target;
            if (h != null)
                h(sender, e);
        };
    }
}

The WeakHandler base class

The WeakHandler is the based class for all delegate type. It provide automatic translation to a weak delegate build by the CreateHandler.

 
public abstract class WeakHandler<T> where T : class
{
    private T handler;
    private T implicitHandler;

    protected WeakHandler(T handler)
    {
        if (handler == null)
            throw new ArgumentNullException("handler");

        if (!(handler is Delegate))
        {
            throw new InvalidOperationException();
        }

        this.handler = handler;
    }

    protected abstract T CreateHandler(WeakReference weakReference);

    public static implicit operator T(WeakHandler<T> weakHandler)
    {
        if (weakHandler == null)
            return null;

        if (weakHandler.implicitHandler == null)
        {
            lock (weakHandler.handler)
            {
                if (weakHandler.implicitHandler == null)
                {
                    var ih = weakHandler.CreateHandler(new WeakReference(weakHandler.handler));
                    Thread.MemoryBarrier();
                    weakHandler.implicitHandler = ih;
                }
            }
        }

        return weakHandler.implicitHandler;
    }
}

 

How to use it

You can use the WeakEventHandler simply as if you where the EventHandler provided by the framework:


Form f = new Form();
f.SizeChanged += new WeakEventHandler(delegate(object sender, EventArgs e)
    {
        Console.WriteLine("Form changed.");
    });

 

Where are we?

We saw how to implement and reuse weak event handler. This event is very easy to create and reuse.

Happy Programming!

Testability of your Linq For Sql Model

I have already spoke with my friends about this. I think it’s the time to post it in my blog. Here is how I shield my implementation from the model.

Use an interface, not the class

Instead of using directly the DataModel generated by the Linq For Sql designer, you could use an interface representing your model.

public interface IDataContext
{
void SaveChanges();
}

public interface IEmployeeModel : IDataContext
{
void AddEmployee(Employee employee);
void DeleteEmployee(Employee employee);
IQueryable<Employee> Employees { get; }
}

We can see here that we have an interface that represent our model.

Customizing the generated partial class

The model generated by the Linq For Sql Designer is using a partial class. Using this feature, we can support for our IEmployeeModel interface. Here is how we do this:

partial class DataClasses1DataContext : IEmployeeModel
{
#region IEmployeeModel Members

public void AddEmployee(Employee employee)
{
if (employee == null)
throw new ArgumentNullException("employee");

this.Employees.InsertOnSubmit(employee);
}

void IEmployeeModel.DeleteEmployee(Employee employee)
{
if (employee == null)
throw new ArgumentNullException("employee");

this.Employees.DeleteOnSubmit(employee);
}

IQueryable<Employee> IEmployeeModel.Employees
{
get { return this.Employees; }
}

#endregion

#region
IDataContext Members

public void SaveChanges()
{
this.SubmitChanges();
}

#endregion
}

Implement a MockEmployeeModel class

After doing our real model, we can create a mock of our model to simulate database for very specific cases without touching the database. This way, we will be able to test even our Linq queries.



public class MockEmployeeModel : IEmployeeModel
{
private List<Employee> employees;

public MockEmployeeModel()
{
this.employees = new List<Employee>();
}

#region IEmployeeModel Members

public void AddEmployee(Employee employee)
{
if (employee == null)
throw new ArgumentNullException("employee");

this.employees.Add(employee);
}

public void DeleteEmployee(Employee employee)
{
if (employee == null)
throw new ArgumentNullException("employee");

this.employees.Remove(employee);
}

public IQueryable<Employee> Employees
{
get { return this.employees.AsQueryable(); }
}

#endregion

#region
IDataContext Members

public void SaveChanges()
{
// Nothing special to do here.
}

#endregion
}

Limitations


  • Compiled Linq queries are not supported. I will probably show you in a next post how to support it.


  • The MockModel is very limited. We would probably benefit having a mocking framework here.

Conclusion

As a typical use, we can now use normal linq queries over our model and test our queries in the very same manner using our MockEmployeeModel. This approach works with ADO.Net Entity Framework as well.



Happy Programming!