Reputation: 61
I am exploring the use of Entity Framework Database First and I am trying to understand if I should inject behavior into an entity, and if so, what is the best technique for doing this. I typically have done this in the past to avoid anemic domain objects. A couple use cases are where I inject a specification into an entity (specification pattern/define composable business rules) or where I perhaps inject a ninject implemented factory into a root entity where the binding of the implementation is determined by a strategy/factory method at point of use) So for example below, I would use an IOC to inject in ISomethingSpec implementation.
class Foo
{
void DoSomething()
{
if(somethingSpec.SatisfiedBy(this)
{
}
}
}
May I ask, Should I consider a different pattern for associating behavior with an entity? Or if it is reasonable, is using partial classes/property and method injection the best option where I am using EF5 with database first?
This is my first post, so I hope it's format is not too far off the mark. I posted as I have looked at other questions that are similar but I could not determine a consensus on best practice for associating behavior with Domain objects /EF Entities.
Upvotes: 2
Views: 1183
Reputation: 61
Re this question, after some investigation following Rui's helpful comments I have concluded that my intention to inject services into an entity is flawed. The answer to my original question therefore is to use Domain Events instead which reduces coupling considerably, or alternatively using 'double dispatch' as per link below. I am currently looking at nServiceBus as the tech for implementing Domain Events (and as an introduction into nServiceBus itself)
The following article helped clear my mind on types of services and how to use with a Domain model:
Upvotes: 2
Reputation: 17994
I use the specification pattern with Entity Framework to filter the data that is retrieved from the database. I think you can use the same approach and adapt it to your needs.
You can use a DI container to inject your specifications and other objects you may need. First step is to define a contract for your specification objects, something like this:
public interface ISpecification<T> where T : class
{
Expression<Func<T, bool>> GetExpression();
bool IsSatisfiedBy(T entity);
}
A generic Specification object can be defined like this:
public class Specification<T> : ISpecification<T> where T : class
{
private Expression<Func<T, bool>> expression;
public Expression<Func<T, bool>> GetExpression()
{
return expression;
}
public Specification(Expression<Func<T, bool>> expression)
{
this.expression = expression;
}
public bool IsSatisfiedBy(T entity)
{
var query = (new[] { entity }).AsQueryable();
return query.Any(this.expression);
}
}
And then you can change your Foo class like this, so you can inject the dependency using a DI/IoC container:
public class Foo()
{
public ISpecification<Foo> Specification
{
get;
private set;
}
public Foo(ISpecification<Foo> specification)
{
this.Specification = specification;
}
public void DoSomething()
{
if(Specification.SatisfiedBy(this))
{
//...
}
}
}
Creating and using a specification:
// example - create one specification
Expression<Func<Foo, bool>> expression = ....;
ISpecification<Foo> fooSpecification = new Specification<Foo>(expression);
// using the specification with linq
var entities = dbContext.Foos.Where(fooSpecification.GetExpression());
// performing validation
var foo = new Foo{
// ....
};
if(fooSpecification.IsSatisfiedBy(foo))
{
// do something....
}
More details here:
Upvotes: 4