【问题标题】:Include derived property into a linq to entity query将派生属性包含到 linq to entity 查询中
【发布时间】:2012-03-08 19:19:02
【问题描述】:

这是一个基于名为Task 的 Poco 类的简单项目:

class Program
{
    static void Main(string[] args)
    {
        using (MyDbContext ctx = new MyDbContext())
        {
            // first query
            DateTime compareDate = DateTime.Now + TimeSpan.FromDays(3);
            var res = ctx.Tasks.Where(t => t.LastUpdate < compareDate).ToList();

            // second query
            res = ctx.Tasks.Where(t => t.ShouldUpdate).ToList();
        }
    }
}

public class MyDbContext : DbContext
{
    public DbSet<Task> Tasks { get; set; }
}

public class Task
{
    public int ID { get; set; }
    public DateTime LastUpdate { get; set; }
    public  bool ShouldUpdate
    {
        get
        {
            return LastUpdate < DateTime.Now + TimeSpan.FromDays(3);
        }
    }
}

我想做的是查询上下文dbset,包括在where子句中的ShouldUpdate派生属性。

“第一个查询工作正常”(我不能把它写在一行但没关系)。

如您所知,我们在“第二个查询”中收到NotSupportedException,并带有以下消息: LINQ to Entities 不支持指定的类型成员“ShouldUpdate”。仅支持初始化器、实体成员和实体导航属性。

没错,我可以理解为什么会这样,但是我需要将派生信息封装在 Task 对象中,这样我就可以在网格中显示该属性或在其他任何地方使用它,而无需重复其背后的逻辑.

有没有一种聪明的技术可以做到这一点?

注意:ShouldUplate 属性的技术名称是什么?衍生的?计算?计算?

【问题讨论】:

    标签: c# linq entity-framework linq-to-entities poco


    【解决方案1】:

    我终于找到了解决方案.. 您可以将部分查询(表达式)存储在静态文件中并像这样使用它们:

    class Program
    {
        static void Main(string[] args)
        {
            using (MyDbContext ctx = new MyDbContext())
            {
                res = ctx.Tasks.Where(Task.ShouldUpdateExpression).ToList();
            }
        }
    }
    
    public class MyDbContext : DbContext
    {
        public DbSet<Task> Tasks { get; set; }
    }
    
    public class Task
    {
        public int ID { get; set; }
        public DateTime LastUpdate { get; set; }
        public bool ShouldUpdate
        {
            get
            {
                return ShouldUpdateExpression.Compile()(this);
            }
        }
    
        public static Expression<Func<Task, bool>> ShouldUpdateExpression
        {
            get
            {
                return t => t.LastUpdate < EntityFunctions.AddDays(DateTime.Now, 3);
            }
        }
    }
    

    【讨论】:

    • 我有类似的问题,但即使我尝试使用上述静态表达式,我也会收到“不支持”错误。知道为什么会这样吗?
    • 你能举个例子吗?
    【解决方案2】:

    在这种情况下,存储库模式将提供更好的抽象。您可以按如下方式集中逻辑。在您的上下文中定义一个新属性 TaskSource

    public class MyDbContext : DbContext
    {
        public DbSet<Task> Tasks { get; set; }
    
        public IQueryable<Task> TaskSource 
        { 
           get 
           { 
              return Tasks.Where(t => t.LastUpdate < EntityFunctions.AddDays(DateTime.Now, 3)); 
           }
        }
    }
    

    【讨论】:

    • so.. 你说数据模型对象根本不应该包含任何逻辑?
    • @user846168 实体可以包含逻辑。放置此类逻辑的适当位置取决于上下文。
    【解决方案3】:

    您需要将 ShouldUpdate 逻辑放在 linq-to-enitites 查询中。您可以使用EntityFunctions.AddDays 来帮助您,就像这样

    res = ctx.Tasks.Where(t => t.LastUpdate < EntityFunctions.AddDays(DateTime.Now, 3)).ToList();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-04
      相关资源
      最近更新 更多