简体   繁体   中英

ASP.NET Web API 2 CRUD Operation with Entity Framework

I am creating a MS Web API 2 project. I have created my Entity Framework in a separate project and am referencing it in my API. Reading over a few tutorials, it is suggested that:

"ideally, we should not return EF entity objects from the Web API. It is recommended to return DTO (Data Transfer Object) from Web API".

Hence, I have created my model in my 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; }
  }
}

My question is: Do I need to create a data context class for each model in my API or is it fine to use EF context class? And if I do need to create a separate context for each model, how can I achieve this by a reference to the EF context class? Below is what I have started with:

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

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

And my Controller is:

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

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

The above correctly throws an error because it cannot convert EF customer to CustomerViewModel directly!

ideally, we should not return EF entity objects from the Web API. It is recommended to return DTO (Data Transfer Object) from Web API.

The reason for this is to make sure you can change your DB schema without changing API, and vice versa. If you accomplish that goal, then you've adhered to that given advice.

The problem you're having is basic. Type A cannot be implicitly converted to Type B . As far as the compiler is concerned, you're trying to convert a DbContext to a FormControl , and it has no idea how to do that. You need to tell it explicitly what to do. One example, albeit not great:

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

and

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

That being said, returning an IQueryable<T> from your Controller is a definite no-no. You definitely want to allow for the consumer to query specific records. You could do this to enable pagination, for instance:

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();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM