我有一个名为Task
的实体。任务可以有子任务。在我的dal中,我每次从实体模型中获取任务时都会尝试自动计算子计数。子计数不存储在数据库中。
例如,让我们看一下我的Fetch方法:
public TaskDto Fetch(Guid id)
{
using (var ctx = ObjectContextManager<MyDataContext>.GetManager("MyDataContext"))
{
var data = (from t in ctx.ObjectContext.Tasks
join tty in ctx.ObjectContext.TaskTypes on t.Id equals tty.Id
where t.EntityGuid == id
select new
{
Task = t,
ChildCount = TaskChildCount(t.EntityGuid)
}).FirstOrDefault();
if (data == null)
{
throw new RecordNotFoundException("Task");
}
return ReadData(data.Task, data.ChildCount);
}
}
但是我没有用2个参数调用ReadData,而只是想用一个任务参数调用它:ReadData(data.Task)
和ChildCount自动在那里。有什么方法可以将它烘焙到我的Task实体中吗?这是一个非常简单的功能:
public int TaskChildCount(Guid currentTaskId)
{
var ret = 0;
using (var ctx = ObjectContextManager<MyDataContext>.GetManager("MyDataContext"))
{
ret = ctx.ObjectContext.Tasks.Count(x => x.ParentId != currentTaskId);
}
return ret;
}
答案 0 :(得分:0)
有一种方法可以做到这一点,但Task
总是需要一些帮助。你可以Include
Task
的儿童记录:
from t in ctx.ObjectContext.Tasks.Include(t => t.Tasks)
现在Task
可以有一个返回TaskCount
的属性this.Tasks.Count
。
您必须在LINQ查询范围之外访问此属性,否则EF将尝试将其转换为SQL并失败。
缺点是它填充了父Task
所包含的所有Task
,这比从数据库中获取计数要重得多。因此,更好的方法是使用AutoMapper
s功能按名称约定投影嵌套属性。假设您的TaskDto
有一个属性TasksCount
,那么您可以这样做:
Mapper.CreateMap<Task, TaskDto>();
var data = ctx.ObjectContext.Tasks.Project().To<TaskDto>();
(Project
是AutoMapper.QueryableExtensions
中的扩展方法,可以通过Nuget获取AutoMapper。
为简单起见,我省略了join
和where
,但这些不会改变这个概念。 AutoMapper在TasksCount
本身中找不到Task
,因此按惯例,它会尝试查找可应用Tasks
的属性Count()
。它找到子集合Tasks
(好吧,也许你用不同的名字命名)然后就去了。您将看到计数整齐地集成在生成的SQL查询中。
不同之处在于dto是由Fetch
方法本身创建的,而不是由ReadData
创建的。我无法判断这是否会导致任何问题。也许您必须随机播放一些代码才能使用此AutoMapper功能。