首页 > 解决方案 > ASP.NET Web API 2 CRUD 操作与实体框架

问题描述

我正在创建一个 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!

标签: c#entity-frameworkasp.net-web-api

解决方案


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

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

你遇到的问题是基本的。TypeA不能隐式转换为 Type B。就编译器而言,您正在尝试将 a 转换DbContext为 a 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();
}

推荐阅读