开发者

EF Relationships and Specification Pattern

开发者 https://www.devze.com 2023-02-20 00:49 出处:网络
I\'ve been looking into the specification pattern for my repositories, I\'m using EF4 inside my repositories to query the database and map the selected entities by passing in an expression, something

I've been looking into the specification pattern for my repositories, I'm using EF4 inside my repositories to query the database and map the selected entities by passing in an expression, something like this:-

public IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> predicate)
{
    return _objectSet.Where<TEntity>(predicate);
}

This works okay if your just working with the one object set but say if you wanted to select all the comments made by a user that are greate开发者_StackOverflow中文版r than 128 chars and the user is active. How would you create a specification when two or more object sets are used?

Example:-

class User
{
    public string Name { get; set; }
    public bool Active { get; set; }
    public virtual ICollection<Post> Posts { get; set; }

    public User()
    {
        Posts = new List<Post>();
    }
}

class Post
{
    public string Text { get; set; }
    public DateTime Created { get; set; }
    public virtual ICollection<Comment> Comments { get; set; }

    public Post()
    {
        Comments = new List<Comment>();
    }
}

class Comment
{
    public string Text { get; set; }
    public DateTime Created { get; set; }
}

To do this in Linq is :-

var results = from u in users
              from p in u.Posts
              from c in p.Comments
              where u.Active && c.Text.Length > 128
              select c;

How would you then convert that to a specification class? Maybe I am just not seeing something as it seems like a reasonable thing to do :)

EDIT

The specification interface:

public interface ISpecification<TEntity>
{
    bool IsSatisfiedBy(TEntity entity);
}


First of all your current setup doesn't allow such query because User and Comment are not related. You can select only all comments related to posts related to user but you don't know who posted comments.

Just add relation between User and Comment and you can simply use:

var results = from c in context.Comments
              where c.User.Active and c.Text.Length > 128
              select c;

This will be easily possible in your Specification pattern. Anyway if you want to build complex condition from Comment in your Find method you must expose navigation properties to allow that.


Funny I was just reading about OCP (Open Closed Principle) and the Specification pattern, and I was wondering whether it's actually worth implementing the Specification pattern in my project. I'm just worried I might end up with a huge pile of specifications due to the fact that I have several entities and I query by several criteria.

Anyway, here's one (actually two) of my favorite blog posts about the patterns you're using (which I'm using as well):

Entity Framework 4 POCO, Repository and Specification Pattern

Specification Pattern In Entity Framework 4 Revisited

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号