C# Web Api 2+EF6-构建DTO

C# Web Api 2+EF6-构建DTO,c#,entity-framework,asp.net-web-api,C#,Entity Framework,Asp.net Web Api,对于一个项目,我们正在使用EF和WebAPI2。为了从数据库模型中抽象出来,我们正在使用DTO。我们有一家工厂来建造这些DTO: public class FooFactory:IModelConverter<FooDTO, Foo> { public FooDTO Create(Foo data) { return new FooDTO() { //Some fields }; } }

对于一个项目,我们正在使用EF和WebAPI2。为了从数据库模型中抽象出来,我们正在使用DTO。我们有一家工厂来建造这些DTO:

public class FooFactory:IModelConverter<FooDTO, Foo>
{

    public FooDTO Create(Foo data)
    {
        return new FooDTO()
        {
           //Some fields
        };
    }
}
在Api调用中,我们可以执行以下操作:

public async Task<IHttpActionResult> GetFoo()
    {
        var foos = db.Foos

        //DO STUFF

         var dtos = (await foos.ToListAsync()).Select(m => _converter.Create(m)); //Converter is an instance of FooFactory)

        return Ok(dtos);
    }
这是可行的,但意味着在执行查询后,我们必须循环所有结果,并将每个模型转换为DTO

另一方面,我们可以做到:

public async Task<IHttpActionResult> GetFoo()
    {
        var foos = db.Foos

        //DO STUFF

        return Ok(await foos.Select(m => new FooDTO() { 
            //Assign fields
        }).ToListAsync());
    }
这将把这个投影集成到EF执行的查询中。但这暴露了FooDTO的所有内部细节,我们必须重复所有这些创建代码

有没有一种方法可以做到:

public async Task<IHttpActionResult> GetFoo()
    {
        var foos = db.Foos

        //DO STUFF

        return Ok(await foos.Select(m => _converter.Create(m)).ToListAsync());
    }
这不起作用,因为Linq to实体无法处理create函数

我也愿意使用其他方法来处理DTO,有没有更好的方法来实现这一点,或者没有办法避免额外传递所有查询结果


哦,问题是,我想在没有automapper的情况下完成这项工作。

首先,这更像是一个代码审查问题。 我建议您不要在控制器的代码中直接使用实体框架数据库。控制器应该是精简的,查询逻辑可能非常复杂。在许多情况下,需要从数据库中查询无法映射到实体的数据。因此,您可以创建直接返回DTO的存储库类:

class FooRepository
{
   public async Task<List<FooDTO>> FindAsync()
   {
       using(var context = new DbContext())
       {
           return await context.Foos
               .Select(m => new FooDTO
               {
                   Id = m.Id,
                   ...
               })
               .ToListAsync();
       } 
   }
}
这种方法的另一个优点是只查询真正需要的数据,现在查询整个实体


注意:wait是必需的-不能在此处直接返回任务。

您始终可以创建匿名对象并返回。您不想在DTO构造函数内部进行映射吗?请注意:如果您先选择,则没有ToListSync,错误,您可以使用System.Data.Entity添加以使扩展方法工作。