Моя проблема в том, что EF Core по умолчанию загружает все мои определенные свойства класса, в то время как я хочу, чтобы он не загружал их, если я специально не запрашиваю их.
Например, возьмем этот простой пример книга с автором (все модели в этом примере одинаковы, но только для того, чтобы показать используемый шаблон):
Сущность базы данных:
using System;
namespace Test.Models.DBModels
{
public partial class Book
{
public int BookId { get; set; }
public int AuthorId { get; set; }
public string Title { get; set; }
public Author Author { get; set; }
}
}
DTO:
using System;
using System.Collections.Generic;
namespace Test.Models.DTOModels
{
public partial class BookDTO
{
public int BookId { get; set; }
public int AuthorId { get; set; }
public string Title { get; set; }
public AuthorDTO Author { get; set; }
}
}
ViewModel:
using System;
using System.Collections.Generic;
namespace Test.Models.ViewModels
{
public partial class BookVM
{
public int BookId { get; set; }
public int AuthorId { get; set; }
public string Title { get; set; }
public AuthorVM Author { get; set; }
}
}
Обратите внимание, что «виртуальные» свойства не используются ни в одном из этих классов, так как я прочитал, что это то, что сказал EF для их автоматического заполнения
DBContext:
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;
using Test.Models.DBModels;
namespace Test.DAL
{
public partial class TestContext : DbContext
{
public TestContext()
{
}
public TestContext(DbContextOptions<TestContext> options)
: base(options)
{
}
public virtual DbSet<Author> Author { get; set; }
public virtual DbSet<Book> Book { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
//optionsBuilder.UseSqlServer("connectionstring");
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
OnModelCreatingPartial(modelBuilder);
}
partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
}
}
Служба:
using AutoMapper;
using System.Collections.Generic;
using System.Linq;
using Test.BLL.Interfaces;
using Test.DAL;
using Test.Models.DomainModels;
using Test.Models.DTOModels;
using Microsoft.EntityFrameworkCore;
using AutoMapper.QueryableExtensions;
using System.Linq.Expressions;
using System;
namespace Test.BLL.Implementations
{
public class BookService : IBookService
{
private readonly TestContext dbContext;
private readonly IMapper _mapper;
public BookService(TestContext dbContext, IMapper mapper)
{
this.dbContext = dbContext;
this._mapper = mapper;
}
public IQueryable<BookDTO> Get()
{
var books = dbContext.Book;
var dto = books.ProjectTo<BookDTO>(_mapper.ConfigurationProvider);
return dto;
}
public IQueryable<BookDTO> Get(params Expression<Func<Book, object>>[] includes)
{
var books = dbContext.Book
.Select(x => x);
foreach (var include in includes)
books = books.Include(include);
var dto = books.ProjectTo<BookDTO>(_mapper.ConfigurationProvider);
return dto;
}
}
}
Контроллер:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AutoMapper;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Test.BLL.Implementations;
using Test.Models.DTOModels;
using Test.Models.ViewModels;
namespace Test.WebAPI.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class BookController : ControllerBase
{
private readonly BookService BookService;
private readonly IMapper _mapper;
public BookController(BookService BookService, IMapper mapper)
{
this.BookService = BookService;
this._mapper = mapper;
}
public IActionResult Index()
{
var books = _mapper.Map<IEnumerable<BookDTO>, IEnumerable<BookVM>>(BookService.Get().ToList());
return Ok(books);
}
}
}
Если я вызываю BookService.Get () .ToList () метод в контроллере, тогда он автоматически заполняет автора в результатах json, например,
{
"bookId":1,
"authorId":1,
"title":"Book A",
"author":{
"authorId":1,
"name":"Some Author"
}
}
В то время как я хочу, чтобы это было:
{
"bookId":1,
"authorId":1,
"title":"Book A",
"author": null
}
Как если бы я хотел заполнить объект Author, я бы вызвал мой перегруженный метод, используя BookService.Get (x => x.Autho r) .ToList ()
Я предполагаю, что это связано с функциональностью активной или отложенной загрузки, но я не уверен, как это сделать. РЕДАКТИРОВАТЬ: Документация описывает их как " Ленивая загрузка означает, что связанные данные прозрачно загружаются из базы данных при обращении к свойству навигации ". Они также говорят, что « Стремительная загрузка означает, что связанные данные загружаются из базы данных как часть начального запроса », что является желаемым поведением, но только для указанных мною свойств.
Есть ли способ в EF Core, чтобы я мог заполнить свойства, только если я специально запрашиваю их включение?