【问题标题】:Entity Framework Core objects cycling实体框架核心对象循环
【发布时间】:2019-12-08 16:59:09
【问题描述】:

我有两个实体:

public class Asset
    {
        public int Id { get; set; }
        public string Name { get; set; }

        [ForeignKey("Type")]
        public short TypeId { get; set; }
        public AssetType Type { get; set; }
    }

public class AssetType
    {
        public short Id { get; set; }
        public string Name { get; set; }
        public ICollection<Asset> Assets { get; set; }
    }

还有我的 DbContext:

public class ApplicationDbContext : DbContext
    {
        public DbSet<Asset> Assets { get; set; }
        public DbSet<AssetAccess> AssetAccesses { get; set; }

        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
        { }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        { }

        protected override void OnModelCreating(ModelBuilder builder)
        {
            base.OnModelCreating(builder);

            builder.Entity<AssetType>().HasIndex(entity => entity.Name).IsUnique();
        }
    }

当我尝试像这样从数据库中选择 Assets 时:

var assets = _dbContext.Assets
    .Include(asset => asset.Type)
    .ToList();

我收到Asset 的列表和他们的Types,但在Type 对象中有关联的Asset 对象列表,因此它会无休止地重复。

[
    {
        "id": 12,
        "name": "asset",
        "type": {
            "id": 1,
            "name": "type",
            "assets": [
                {
                    "id": 12,
                    "name": "asset",
                    "type": {
                        ... and so on ...
                    }
                },
                {
                    "id": 13,
                    "name": "asset",
                    "type": {
                        ... and so on ...
                    }
                }
            ]
        },
    },
    ...
]

我只想接收带有内部TypeAsset 列表,仅此而已。那么我怎样才能摆脱这种循环呢? 在启动时我定义了这个:

services.AddMvc()
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
    .AddJsonOptions(option => option.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore);

但它不起作用。

【问题讨论】:

  • 你应该返回视图模型而不是你的实体。
  • @CodeNotFound ,是的,我这样做了。但我使用 AutoMapper 将我的域模型转换为视图模型。当域模型具有循环引用时,AutoMapper 返回更多对象,那么它必须而且我不想返回额外的无用数据
  • @Artyom DTO/视图模型的整个想法是它们不应该有循环引用——你只创建你需要的属性。 EF(存储)实体模型中的循环引用没有问题 - EF 正在正确处理它们,而 AM(尤其是投影)也可以做到这一点。
  • 你当前的 ViewModel 是什么?

标签: linq asp.net-core entity-framework-core


【解决方案1】:

对于返回 ViewModel 而不附加循环对象,请尝试按照以下步骤操作:

  1. 视图模型

    public class AssetVM
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public AssetTypeVM Type { get; set; }
    }
    
    public class AssetTypeVM
    {
        public short Id { get; set; }
        public string Name { get; set; }
    }
    
  2. 简介

    public class ModelProfile: Profile
    {
        public ModelProfile()
        {
            CreateMap<AssetType, AssetTypeVM>();
            CreateMap<Asset, AssetVM>();
        }
    }
    
  3. 使用

    var assets = _context.Assets
                .Include(asset => asset.Type)
                .ToList();
    var assetsVM = _mapper.Map<List<AssetVM>>(assets);
    

【讨论】:

    【解决方案2】:

    您可以尝试将 virtual 关键字添加到 Type 和 Assets 属性吗?这应该使它们能够延迟加载,因此您不应该得到循环引用?

    您可以在此处阅读更多信息:navigation property should be virtual - not required in ef core

    您也可以尝试添加此设置:

    services.AddMvc().AddJsonOptions(options => {
                options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
            });
    

    【讨论】:

    • 如果您只有一小段示例代码无法正常工作,您能否将其提供给我,以便我对其进行测试?
    • 抱歉,这是我的工作项目,我不能分享。但我可以提供更多相关信息。我使用 asp core 2.2、Mysql 8.0 数据库、EF Core 和Pomelo.EntityFrameworkCore.MySql nuget 包、AutoMapper.Extensions.Microsoft.DependencyInjection。顺便说一句,我需要在对数据库的选择请求期间或在 autoMapper 模型映射期间摆脱循环引用
    • 是的,我已经尝试过配置 Json 选项,它可以防止映射器返回异常,但无论如何它提供的内部对象比它必须的要多
    猜你喜欢
    • 2021-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-26
    • 2021-07-14
    • 1970-01-01
    • 1970-01-01
    • 2019-02-27
    相关资源
    最近更新 更多