1

我有一个名为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,我只想用一个 Task 参数调用它:ReadData(data.Task)并且 ChildCount 自动在那里。有什么方法可以将它烘焙到我的任务实体中吗?这是一个非常简单的功能:

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;
}
4

1 回答 1

0

There is a way to do this, but Task will always need some help. You could Include the child records of Task:

from t in ctx.ObjectContext.Tasks.Include(t => t.Tasks)

Now Task can have a property TaskCount that returns this.Tasks.Count.

You'd have to access this property outside the scope of a LINQ query, otherwise EF will try to translate it into SQL and fail.

The downside is that it populates all Tasks contained by a parent Task, which is a lot heavier than just getting a count from the database. Therefore a better way could be to use AutoMappers capability to project nested properties by name convention. Suppose your TaskDto would have a property TasksCount, then you could do:

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

(Project is an extension method in AutoMapper.QueryableExtensions, AutoMapper can be obtained through Nuget).

I leave out the join and where for simplicity, but these would not change the concept. AutoMapper does not find TasksCount in Task itself, so by convention it tries to find a property Tasks to which it can apply Count(). It finds the child collection Tasks (well, maybe you named it differently) and there you go. You will see that the count is neatly integrated in the SQL query that is generated.

The difference is that the dto is created by the Fetch method itself, not by ReadData. I can't judge whether this causes any problems. Maybe you have to shuffle some code in order to use this AutoMapper feature.

于 2013-08-02T18:30:41.197 回答