ASP.NET Web API 2使用实体框架的CRUD操作

时间:2018-06-06 20:49:26

标签: c# entity-framework asp.net-web-api

我正在创建一个MS Web API 2项目。我在一个单独的项目中创建了我的实体框架,并在我的API中引用它。阅读一些教程,建议:

"理想情况下,我们不应该从Web API返回EF实体对象。建议从Web API"。

返回DTO(数据传输对象)

因此,我在我的API中创建了我的模型:

namespace MyAPI.Models
{
  [Table("Customer")]
  public class CustomerViewModel
  {
    [Key]
    public int CustomerID { get; set; }
    public string Code { get; set; }
    public string Name { get; set; }
  }
}

我的问题是:我是否需要为我的API中的每个模型创建一个数据上下文类,或者使用EF上下文类是否合适?如果我确实需要创建一个单独的上下文每个模型,如何通过引用EF上下文类来实现这一目标?以下是我的开始:

namespace MyAPI.Models
{
   public class CustomerDbContext : DbContext
   {
       public CustomerDbContext() : base("name=CusetomerDbContext")
       {
       }

       public DbSet<MyEFDataAccess.Customer> CustomerViewModel { get; set; }
   }
}

我的控制器是:

namespace MyAPI.Controllers
{
   public class CustomersController : ApiController
   {
    private readonly CustomerDbContext _context = new CustomerDbContext();

    // GET: api/Customer
    public IQueryable<CustomerViewModel> GetCustomerViewModels()
    {
        return _context.CustomerViewModel;
    }
}

以上正确抛出错误,因为它无法直接将EF客户转换为CustomerViewModel!

1 个答案:

答案 0 :(得分:3)

  

理想情况下,我们不应该从Web API返回EF实体对象。它   建议从Web API返回DTO(数据传输对象)。

这样做的原因是为了确保您可以在不更改API的情况下更改数据库架构,反之亦然。如果你实现了这个目标,那么你就已经遵守了这个建议。

你遇到的问题是基本的。类型A无法隐式转换为类型B。就编译器而言,您正在尝试将DbContext转换为FormControl,并且它不知道如何执行此操作。你需要明确告诉它该做什么。一个例子,虽然不是很好:

public DbSet<MyEFDataAccess.Customer> Customer { get; set; }

public IQueryable<CustomerViewModel> GetCustomerViewModels()
{
    return _context.Customer.Select(
        customer => new CustomerViewModel
        {
            // <assign properties here>
        }
    );
}

话虽这么说,从你的控制器返回IQueryable<T>是一个肯定的禁忌。您肯定希望允许使用者查询特定记录。您可以执行此操作以启用分页,例如:

public async Task<List<CustomerViewModel>> GetCustomerViewModels(
    int skip = 0,
    int take = 100
)
{
    return await _context.Customer
        .Skip(skip)
        .Take(take)
        .Select(
            customer => new CustomerViewModel
            {
                // <assign properties here>
            }
        )
        .ToListAsync();
}