如何在linq中为实体写几个类型的泛型?

时间:2014-12-09 09:51:51

标签: c# entity-framework reflection entity-framework-6

我有很多课程

public class City
{
    public int CityID { get; set; }
    public string Name { get; set; }
    public string Comment { get; set; }
    public virtual ICollection<ApplicationUser> DryCleanings { get; set; }
    public DateTime DateCreated { get; set; }
    public DateTime DateChanged { get; set; }
    public bool IsDeleted { get; set; }
}

    public class Marker
{
    public int MarkerID { get; set; }
    public string Name { get; set; }
    public string Comment { get; set; }
    public byte[] Icon { get; set; }
    public virtual IEnumerable<ApplicationUser> Cleanings { get; set; }
    public DateTime DateCreated { get; set; }
    public DateTime DateChanged { get; set; }
    public bool IsDeleted { get; set; }
}
.
.
.

它们都具有相同的三个属性

    public DateTime DateCreated { get; set; }
    public DateTime DateChanged { get; set; }
    public bool IsDeleted { get; set; }

我需要在每个查询中写相同的内容,类似这样的

_db.Cities.Where(c => !c.IsDeleted && c.DateChanged > oldDate && c.DateChanged < oldDate);
_db.Markers.Where(m => !m.IsDeleted && m.DateChanged > oldDate && m.DateChanged < oldDate);

我不想为每个类编写此查询。我可以写一次这个谓词并用于所有人吗?

PS。我尝试从Interface

继承
    public interface IDate
{
    public DateTime DateCreated { get; set; }
    public DateTime DateChanged { get; set; }
    public bool IsDeleted { get; set; }
}

并写下这样的东西

 Expression<Func<IDate, bool>> lessOldDate = c => !c.IsDeleted && c.DateChanged > oldDate && c.DateChanged < oldDate;

但我得到IDate类型,但我需要Marker

enter image description here

3 个答案:

答案 0 :(得分:3)

您可以通过定义通用方法,以较少强制的方式解决此问题(而不是使用Enumerable.CastEnumerable.OfType):

public static IQueryable<T> WhereLessOld<T>(this IQueryable<T> source, DateTime oldDate)
    where T : IDate
{
    return source.Where(c => !c.IsDeleted && c.DateChanged > oldDate && c.DateChanged < oldDate);
}

注意:如果您使用的LINQ提供程序无法正确处理接口,则上述代码可能存在问题 - 在这种情况下,您可以使用以下代码:

using System;
using System.Linq;
using System.Linq.Expressions;

public static IQueryable<T> WhereLessOld<T>(this IQueryable<T> source, DateTime oldDate)
    where T : IDate
{
    var param = Expression.Parameter(typeof(T));
    var filterExpression =
        Expression.And(
            Expression.Not(Expression.Property(param, "IsDeleted")),
            Expression.And(
                Expression.GreaterThan(
                    Expression.Property(param, "DateChanged"),
                    Expression.Constant(oldDate)
                ),
                Expression.LessThan(
                    Expression.Property(param, "DateChanged"),
                    Expression.Constant(oldDate)
                )
            )
        );
    var delegateExpression = Expression.Lambda<Func<T, bool>>(filterExpression, param);

    return source.Where(delegateExpression);
}

然后你可以写:

var testQuery = db.Markers.WhereLessOld(oldDate);

答案 1 :(得分:2)

使用Enumerable.OfType

var testQuery = db.Markers.Where(lessOldDate).OfType<Marker>().ToList();

答案 2 :(得分:1)

使用Cast方法:

var testQuery=db.Markers.Where(lessOldDate).Cast<Marker>();

另见related question