C# 在LINQ查询中对基类使用扩展方法

C# 在LINQ查询中对基类使用扩展方法,c#,linq,entity-framework,extension-methods,covariance,C#,Linq,Entity Framework,Extension Methods,Covariance,为我的天真提前道歉 我正在使用实体框架来持久化我在域模型中定义的实体。我的域模型实体都继承自我的EntityBase类。这具有我希望对我的所有实体通用的属性: public class EntityBase { public string CreatedBy { get; set; } public DateTime? Created { get; set; } public int ModifiedBy { get; set; } public DateTim

为我的天真提前道歉

我正在使用实体框架来持久化我在域模型中定义的实体。我的域模型实体都继承自我的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);
    }
公共静态IQueryable活动(此IQueryable entityCollection)
{
返回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);
var messages=_db.Memberships.Where(m=>m.UserId.Equals(UserId))
.SelectMany(m=>m.Group.Messages)
.Include(m=>m.Group.Category)

.Active()您可以通过更改扩展方法:

public static IQueryable<T> Active(this IQueryable<T> entityCollection)
    where T : EntityBase
{
    return entityCollection.Where(e => e.Enabled && !e.Deleted);
}
公共静态IQueryable活动(此IQueryable entityCollection)
其中T:EntityBase
{
返回entityCollection.Where(e=>e.Enabled&&!e.Deleted);
}

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

public static IQueryable<T> Active<T>(this IQueryable<T> entityCollection) where T:EntityBase
{
    return entityCollection.Where(e => e.Enabled && !e.Deleted);
}
公共静态IQueryable活动(此IQueryable entityCollection),其中T:EntityBase
{
返回entityCollection.Where(e=>e.Enabled&&!e.Deleted);
}
我假设您使用的是早于4.0的.NET版本。在4.0之前是不允许的(即在需要基类型的枚举时传递子类型的枚举)


即使在4.0之后,使用协方差也不是绝对最好的主意,因为每当您尝试将一些新值存储到列表中时,编译器都会执行大量额外的检查以确保类型安全。Jon Skeet有一个

您的错误不在查询中,而是在返回点。将鼠标悬停在
messages
var
上,查看其类型是否符合您的预期。我打赌使用.NET 3.5?非常感谢您,这样做很有意义。然而,当我尝试使用通用版本IQueryable时,VisualStudio总是抱怨它无法解决问题。我到底错过了什么?觉得自己很愚蠢!顺便提一下,该项目是一个类库,目标是.NET4.5?非常感谢您的帮助。Ooops,声明中缺少了抱歉的Panagiotis-代码正是上面的代码,但是按照您的建议添加了和where T:EntityBase位。编辑器中的错误为“无法解析符号T”。我需要添加一个using指令来使用泛型类型吗?您好,我错过了您的评论。好极了,现在一切都好了。非常非常感谢。
public static IQueryable<T> Active<T>(this IQueryable<T> entityCollection) where T:EntityBase
{
    return entityCollection.Where(e => e.Enabled && !e.Deleted);
}