定义动态实体属性/函数

时间:2013-08-02 10:51:57

标签: c# entity-framework

我有一个名为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;
}

1 个答案:

答案 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,这比从数据库中获取计数要重得多。因此,更好的方法是使用AutoMappers功能按名称约定投影嵌套属性。假设您的TaskDto有一个属性TasksCount,那么您可以这样做:

Mapper.CreateMap<Task, TaskDto>();
var data = ctx.ObjectContext.Tasks.Project().To<TaskDto>();

ProjectAutoMapper.QueryableExtensions中的扩展方法,可以通过Nuget获取AutoMapper。

为简单起见,我省略了joinwhere,但这些不会改变这个概念。 AutoMapper在TasksCount本身中找不到Task,因此按惯例,它会尝试查找可应用Tasks的属性Count()。它找到子集合Tasks(好吧,也许你用不同的名字命名)然后就去了。您将看到计数整齐地集成在生成的SQL查询中。

不同之处在于dto是由Fetch方法本身创建的,而不是由ReadData创建的。我无法判断这是否会导致任何问题。也许您必须随机播放一些代码才能使用此AutoMapper功能。