【问题标题】:EF Core: loading related entities - circular dependencyEF Core:加载相关实体 - 循环依赖
【发布时间】:2016-08-01 02:58:51
【问题描述】:

我在 EF Core 中有 2 个相关实体(来自现有数据库的数据库优先设计)并且无法加载一对多关系 - 它是一个 webapi ASP.NET Core 1.0 应用程序

品牌实体

 [Table("tblBranding")]
public class Brand {
    [Key]
    [Column("brandingId")]
    public int BrandId { get; set; }
    [Column("BrandingActive")]
    public bool Active { get; set; }
    [JsonIgnore]
    [Column("DeadBrand")]        
    public bool DeadBrand { get; set; }
    [Column("BrandingSiteTitle")]
    public string Name { get; set; }

    //navigation properties
    public virtual ICollection<Event> Events { get; set; }
}

事件实体:

[Table("tblEvents")]
public class Event
{   
    public int EventId { get; set; }
    [Column("eventActive")]
    public bool Active { get; set; }
    [Column("eventName")]
    public string Name { get; set; }        
    public DateTime EventCloseDate {get;set;}        
    public int PaxAllocationLimit { get; set; }

    //navigation properties                
    [Column("BrandingId")]
    public int BrandId { get; set; }        
    public virtual Brand Brand { get; set; }
    public virtual ICollection<Session> Sessions { get; set; }

}

DbContext 中 OnModelCreating 中 FLUID API 的代码:

modelBuilder.Entity<Event>()
            .HasOne(e => e.Brand)
            .WithMany(b => b.Events).HasForeignKey(e=>e.BrandId);

    public virtual DbSet<Brand> Brands { get; set; }
    public virtual DbSet<Event> Events { get; set; }  

来自 BrandsController 的代码:

    [HttpGet]
    public IActionResult Get() {
        //var brands = from b in _context.Brands
        //             where b.Active == true
        //             orderby b.BrandName
        //             select b;

        var brands = _context.Brands.Include(e => e.Events).Where(b => b.Active == true).OrderBy(b => b.Name);

        return new ObjectResult(brands);
    }   

EventsController 中的代码

 // GET: api/values
    [HttpGet("{id:int?}")]
    public IActionResult Get(int? id) {
        var events = from e in _context.Events
                     where e.Active == true
                     orderby e.Name
                     select e;

        if (!events.Any()) {
            return HttpNotFound();
        }

        if (id != null) {
            events = events.Where(e => e.EventId == id).OrderBy(e => 0);
            if (events.Count() == 0) { return HttpNotFound(); }
            return new ObjectResult(events);
        }
        else {
            return new ObjectResult(events);
        }
    }

当我尝试通过 API 加载品牌时,出现异常:

Microsoft.Data.Entity.Storage.Internal.RelationalCommandBuilderFactory:信息:已执行 DbCommand (80ms) [Parameters=[], CommandType='Text', CommandTimeout='30'] 选择 [t].[EventId], [t].[EventCloseDate], [t].[eventActive], [t].[BrandingId], [t].[EventId1], [t].[eventName], [ t].[PaxAllocationLimit] 从 [tblEvents] 作为 [t] 内部联接 ( SELECT DISTINCT [e].[BrandingSiteTitle], [e].[brandingId] FROM [tblBranding] 作为 [e] WHERE [e].[BrandingActive] = 1 ) AS [e] ON [t].[BrandingId] = [e].[brandingId] ORDER BY [e].[BrandingSiteTitle], [e].[brandingId] Microsoft.Data.Entity.Query.Internal.SqlServerQueryCompilationContextFactory:错误:迭代查询结果时数据库中发生异常。 System.Data.SqlClient.SqlException (0x80131904):列名“EventId1”无效。

除此之外,有没有办法在不使用“包含”的情况下加载相关实体?如果我不使用包含并使用标准 LINQ 查询,相关实体将加载为 NULL

更新

我现在收到无效列错误 - 我注意到在我之前的代码中我没有在品牌的 ICollection 上使用 virtual

现在我无法弄清楚为什么它会在 SQL 中生成 EventId1 列

EF 7 版本是 1.0.0-rc1-final

UPDATE-2 在使用与上面完全相同的代码的情况下,异常更改为代码中的循环依赖异常 - 我不知道为什么它之前生成了无效的列名(EventId1)

【问题讨论】:

  • 异常发生在哪里?序列化响应时?你能检查一下 query.FirstOrDefault() 没有抛出任何异常吗?
  • 更新了我遇到的代码和问题 - 我认为我遇到了上一个问题,因为我没有在 collections 属性上使用 virtual
  • 您在使用 EF 迁移吗?
  • 使用 EF Scaffolding - 来自现有数据库 - 但是,数据库中的表很大,我的模型是表的简化版本,可满足我在 modelBuilder 中映射 API 所需的内容
  • 我根据您提供的信息构建了一个示例解决方案,没有任何错误

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


【解决方案1】:

在这里回答我自己的问题-想通了-

这里使用的 2 个实体,我在 EF 7 中使用了完全定义的关系 - 但是 JSON 序列化程序不喜欢这样,因为这会创建循环依赖 - 品牌包含事件列表,并且每个事件还包含父品牌属性 -

所以这里的解决方案是将 [JsonIgnore] 属性添加到孩子的关系属性中

更新的事件类:

[Table("tblEvents")]
public class Event
{   
    public int EventId { get; set; }
    [Column("eventActive")]
    public bool Active { get; set; }
    [Column("eventName")]
    public string Name { get; set; }        
    public DateTime EventCloseDate {get;set;}        
    public int PaxAllocationLimit { get; set; }

    //navigation properties             
    [JsonIgnore]
    [Column("brandingId")]
    public virtual int BrandId { get; set; }
    [JsonIgnore]
    public virtual Brand Brand { get; set; }
    //public virtual ICollection<Session> Sessions { get; set; }

}

【讨论】:

  • 好吧,您不必[JsonIgnore] ID,但您必须忽略子对象和/或子列表对象
猜你喜欢
  • 2019-02-13
  • 1970-01-01
  • 1970-01-01
  • 2019-11-11
  • 2018-02-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-15
相关资源
最近更新 更多