将派生属性包含到linq到实体查询中
本文关键字:实体 查询 linq 属性 包含 派生 | 更新日期: 2023-09-27 18:25:07
下面是一个基于名为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
物业的技术名称是什么?派生?计算计算?
我终于找到了解决方案。。您可以将部分查询(表达式)存储在静态文件中,并像这样使用它们:
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);
}
}
}
Repository模式将提供更好的抽象。您可以按如下方式集中逻辑。在上下文中定义一个新属性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));
}
}
}
您需要将ShouldUpdate逻辑放入linq-to-enitites查询中。你可以使用EntityFunctions.AddDays来帮助你,就像一样
res = ctx.Tasks.Where(t => t.LastUpdate < EntityFunctions.AddDays(DateTime.Now, 3)).ToList();