4

提前为我的幼稚道歉。

我正在使用实体框架来持久化我在域模型中定义的实体。我的域模型实体都继承自我的 EntityBase 类。这具有我希望所有实体共有的属性:

public class EntityBase
{
    public string CreatedBy { get; set; }
    public DateTime? Created { get; set; }

    public int ModifiedBy { get; set; }
    public DateTime? Modified { get; set; }

    public bool Enabled { get; set; }
    public bool Deleted { get; set; }
}

现在,当我想使用 LINQ 查询 EF 时,如果我不必包含元素来检查特定实体是否已启用或已删除,那就太好了。每个查询都会涉及代码,例如:

var messages = _db.Memberships.Where(m => m.UserId.Equals(userId))
                              .SelectMany(m => m.Group.Messages)
                              .Include(m => m.Group.Category)
                              .Select(m => m.Enabled && !m.Deleted) 
                              .ToList();

而不是每次都这样做,我想我会写一个扩展方法来作用于 IQueryable

public static IQueryable<EntityBase> Active(this IQueryable<EntityBase> entityCollection)
    {
        return entityCollection.Where(e => e.Enabled && !e.Deleted);
    }

然后我天真地认为我可以将它包含在任何 LINQ 查询中,该查询返回我从 EntityBase 类继承的实体 - 如下所示:

var messages = _db.Memberships.Where(m => m.UserId.Equals(userId))
            .SelectMany(m => m.Group.Messages)
            .Include(m => m.Group.Category)
            .Active() <============================= Extension Methd
            .ToList();

        return Mapper.Map<List<Message>,List<MessageDto>>(messages);

但是,编译器现在抱怨:

Error 2 Argument 1: cannot convert from
          'System.Collections.Generic.List<Diffusr.Business.Entities.EntityBase>' to
          'System.Collections.Generic.List<Diffusr.Business.Entities.Message>'  

问题:我能否实现我想要实现的目标,即我的所有实体只返回启用而不是删除的通用方法?如果是这样,怎么做?

4

2 回答 2

4

与大多数扩展方法一样,使用泛型而不是指定具体类:

public static IQueryable<T> Active<T>(this IQueryable<T> entityCollection) where T:EntityBase
{
    return entityCollection.Where(e => e.Enabled && !e.Deleted);
}

我假设您使用的 .NET 版本早于 4.0。在 4.0 之前不允许使用泛型协方差(即,在需要基类型的可枚举时传递子类型的可枚举)。

即使在 4.0 之后,使用协方差也不是绝对最好的主意,因为当您尝试将一些新值存储到 List 时,编译器最终会进行大量额外检查以确保类型安全。Jon Skeet 有一篇关于这个的好文章

于 2013-10-10T12:27:30.200 回答
3

您可以通过更改扩展方法:

public static IQueryable<T> Active(this IQueryable<T> entityCollection)
    where T : EntityBase
{
    return entityCollection.Where(e => e.Enabled && !e.Deleted);
}
于 2013-10-10T12:27:22.727 回答