代码之家  ›  专栏  ›  技术社区  ›  Peter

EF子类的核心负载数据

  •  0
  • Peter  · 技术社区  · 2 年前

    我已设法加载子类型的数据 ImageCell TextCell 属于 Cell .

    public abstract class Cell : IAggregateRoot
    {
        public int CellId { get; set; }
        public string CellType { get; set; }
        public int RowIndex { get; set; }
        public int ColIndex { get; set; }
        public int RowSpan { get; set; }
        public int ColSpan { get; set; }
        public int PageId { get; set; }
        public Page Page { get; set; }
    }
    
    public class TextCell : Cell
    {
        public String Text { get; set; }
    }
    
    public class ImageCell : Cell
    {
        public String Url { get; set; }
    }
    

    我添加了的鉴别器值 CellType 基于枚举。

    public enum CellEnum
    {
        Cell,
        TextCell,
        ImageCell
    }
    

    DbContext.OnModelCreating() 我是这样配置的:

    builder.Entity<Cell>()
        .HasDiscriminator(c => c.CellType)
        .IsComplete(false);
    

    从那时起,我想我通过创建一个服务 CellType .

    Program.cs

    builder.Services.AddScoped<IService<Cell>, GenericService<Cell>>();
    builder.Services.AddScoped<IService<ImageCell>, GenericService<ImageCell>>();
    builder.Services.AddScoped<IService<TextCell>, GenericService<TextCell>>();
    

    IService.cs

    namespace Core.Interfaces
    {
        public interface IService<T> where T : class, IAggregateRoot
        {
            Task<T> GetByIdAsync(int id);
            Task<IEnumerable<T>> ListAsync();
            // Adapt to use specifications
            Task<IEnumerable<T>> ListAsyncWithSpec(Specification<T> spec);
            Task DeleteByIdAsync(int id);
            Task AddAsync(T t);
            Task UpdateAsyc(T t);
        }
    }
    

    GenericService 只是使用的存储库的实现 IService<T> .

    然后我创建了一个 DTO .

    namespace API.DTOs
    {
        public class CellDTO : DTO
        {        
            public int CellId { get; set; }
            public string CellType { get; set; }
            public int RowIndex { get; set; }
            public int ColIndex { get; set; }
            public int RowSpan { get; set; }
            public int ColSpan { get; set; }
            public int PageId { get; set; }
            // CellType specific properties
            public string Url { get; set; }
            public string Text { get; set; }
        }
    }
    

    并创建了 MappingProfile .

    CreateMap<Cell, CellDTO>()
        .ForMember(dto => dto.Text, options => options.MapFrom(src => src.CellType.Equals(CellEnum.TextCell.ToString()) ? ((TextCell)src).Text : null))
        .ForMember(dto => dto.Url, options => options.MapFrom(src => src.CellType.Equals(CellEnum.ImageCell.ToString()) ? ((ImageCell)src).Url : null));
    

    控制器现在看起来真的很乱:

    namespace API.Controllers
    {
        [Route("api/[controller]")]
        [ApiController]
        public class CellsController : BaseController<Cell, CellDTO>
        {
            private readonly IService<ImageCell> _imageCellService;
            private readonly IService<TextCell> _textCellService;
    
            public CellsController(IService<Cell> service, IService<ImageCell> imageCellService, IService<TextCell> textCellService, IMapper mapper) : base(service, mapper)
            {
                _imageCellService = imageCellService;
                _textCellService = textCellService;
            }
    
            [HttpGet]
            public override async Task<ICollection<CellDTO>> Get()
            {
                var result = new List<CellDTO>();
    
                // Add ImageCells
                ICollection<ImageCell> imageCells = (ICollection<ImageCell>)await _imageCellService.ListAsync();
                result.AddRange(_mapper.Map<ICollection<ImageCell>, ICollection<CellDTO>>(imageCells));
    
                // Add TextCells
                ICollection<TextCell> textCells = (ICollection<TextCell>)await _textCellService.ListAsync();
                result.AddRange(_mapper.Map<ICollection<TextCell>, ICollection<CellDTO>>(textCells));
    
                return result;
            }
        }
    }
    

    我如何在不复制这么多代码和使用多个的情况下加载所有子类 I服务<T> 对于每种专用类型?

    编辑#1

    我正在使用 Ardalis.Specification ,但找不到任何有用的东西。

    using Ardalis.Specification;
    using Core.Entities.Cells;
    
    namespace Core.Specifications
    {
        public class CellSpecification : Specification<Cell>
        {
            public CellSpecification()
            {
                
            }
        }
    }
    

    编辑#2

    示例输出

    [
      {
        "cellId": 1,
        "cellType": "ImageCell",
        "rowIndex": 0,
        "colIndex": 0,
        "rowSpan": 1,
        "colSpan": 1,
        "pageId": 1,
        "url": "http://bild0.png",
        "text": null
      },
      {
        "cellId": 2,
        "cellType": "ImageCell",
        "rowIndex": 0,
        "colIndex": 0,
        "rowSpan": 1,
        "colSpan": 1,
        "pageId": 2,
        "url": "http://bild1.png",
        "text": null
      },
      {
        "cellId": 3,
        "cellType": "ImageCell",
        "rowIndex": 0,
        "colIndex": 0,
        "rowSpan": 1,
        "colSpan": 1,
        "pageId": 3,
        "url": "http://bild2.png",
        "text": null
      },
      {
        "cellId": 4,
        "cellType": "ImageCell",
        "rowIndex": 0,
        "colIndex": 0,
        "rowSpan": 1,
        "colSpan": 1,
        "pageId": 4,
        "url": "http://bild3.png",
        "text": null
      },
      {
        "cellId": 5,
        "cellType": "ImageCell",
        "rowIndex": 0,
        "colIndex": 0,
        "rowSpan": 1,
        "colSpan": 1,
        "pageId": 5,
        "url": "http://bild4.png",
        "text": null
      },
      {
        "cellId": 6,
        "cellType": "TextCell",
        "rowIndex": 0,
        "colIndex": 1,
        "rowSpan": 1,
        "colSpan": 2,
        "pageId": 1,
        "url": null,
        "text": "Es ist..."
      },
      {
        "cellId": 7,
        "cellType": "TextCell",
        "rowIndex": 0,
        "colIndex": 1,
        "rowSpan": 1,
        "colSpan": 2,
        "pageId": 2,
        "url": null,
        "text": "Borja hockt..."
      },
      {
        "cellId": 8,
        "cellType": "TextCell",
        "rowIndex": 0,
        "colIndex": 1,
        "rowSpan": 1,
        "colSpan": 2,
        "pageId": 3,
        "url": null,
        "text": "..."
      },
      {
        "cellId": 9,
        "cellType": "TextCell",
        "rowIndex": 0,
        "colIndex": 1,
        "rowSpan": 1,
        "colSpan": 2,
        "pageId": 4,
        "url": null,
        "text": "«Das Versteck ..."
      },
      {
        "cellId": 10,
        "cellType": "TextCell",
        "rowIndex": 0,
        "colIndex": 1,
        "rowSpan": 1,
        "colSpan": 2,
        "pageId": 5,
        "url": null,
        "text": "Die Ameise...:"
      }
    ]
    
    1 回复  |  直到 2 年前
        1
  •  1
  •   David Browne - Microsoft    2 年前

    Cell是一个实体,所以只需运行

    var cells = await db.Set<Cell>().ToListAsync();
    

    并删除或修复并简化IService,如下所示:

    public interface IService<T> where T : class, IAggregateRoot
    {
        Task<T> GetByIdAsync(int id);
        IQueryable<T> All();
        Task DeleteByIdAsync(int id);
        Task AddAsync(T t);
        Task UpdateAsyc(T t);
    }
    

    你可以这样使用

    var cells = await cellService.All().ToListAsync();