EF Core:加载相关实体——循环依赖
EF Core: loading related entities - circular dependency
我在 EF Core 中有 2 个相关实体(基于现有数据库的数据库优先设计)并且无法加载一对多关系 - 它是一个 webapi ASP.NET 核心 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(80 毫秒)[Parameters=[],CommandType='Text',CommandTimeout='30']
SELECT [t].[EventId], [t].[EventCloseDate], [t].[eventActive], [t].[BrandingId], [t].[EventId1], [t].[事件名称], [t].[PaxAllocationLimit]
来自 [tblEvents] 作为 [t]
内部联接 (
SELECT DISTINCT [e].[BrandingSiteTitle], [e].[brandingId]
从 [tblBranding] AS [e]
其中 [e].[BrandingActive] = 1
) AS [e] ON [t].[BrandingId] = [e].[brandingId]
按 [e].[BrandingSiteTitle]、[e].[brandingId] 排序
Microsoft.Data.Entity.Query.Internal.SqlServerQueryCompilationContextFactory:错误:迭代查询结果时数据库发生异常。
System.Data.SqlClient.SqlException (0x80131904): 列名无效 'EventId1'.
除此之外,有没有一种方法可以在不使用 "Includes" 的情况下加载相关实体?如果我不使用 include 而是使用标准的 LINQ 查询,相关实体将加载为 NULL
更新
我现在收到一个无效列错误 - 我注意到在我之前的代码中我没有在 brand
的 ICollection 上使用 virtual
现在我不明白为什么它会在 SQL
中生成 EventId1 列
EF 7 版本为 1.0.0-rc1-final
UPDATE-2
在使用代码后,异常在代码中变为循环依赖异常,代码与上面完全相同——我不知道为什么它早些时候生成了无效的列名 (EventId1)
在这里回答我自己的问题 - 弄明白了 -
这里使用的 2 个实体,我在 EF 7 中使用了完全定义的关系
- 然而 JSON 序列化程序不喜欢那样,因为这会产生循环依赖 - 品牌包含事件列表,并且每个事件还包含父品牌 属性 -
所以这里的解决方案是将 [JsonIgnore] 属性添加到子项的关系属性中
更新事件 class:
[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; }
}
我在 EF Core 中有 2 个相关实体(基于现有数据库的数据库优先设计)并且无法加载一对多关系 - 它是一个 webapi ASP.NET 核心 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(80 毫秒)[Parameters=[],CommandType='Text',CommandTimeout='30'] SELECT [t].[EventId], [t].[EventCloseDate], [t].[eventActive], [t].[BrandingId], [t].[EventId1], [t].[事件名称], [t].[PaxAllocationLimit] 来自 [tblEvents] 作为 [t] 内部联接 ( SELECT DISTINCT [e].[BrandingSiteTitle], [e].[brandingId] 从 [tblBranding] AS [e] 其中 [e].[BrandingActive] = 1 ) AS [e] ON [t].[BrandingId] = [e].[brandingId] 按 [e].[BrandingSiteTitle]、[e].[brandingId] 排序 Microsoft.Data.Entity.Query.Internal.SqlServerQueryCompilationContextFactory:错误:迭代查询结果时数据库发生异常。 System.Data.SqlClient.SqlException (0x80131904): 列名无效 'EventId1'.
除此之外,有没有一种方法可以在不使用 "Includes" 的情况下加载相关实体?如果我不使用 include 而是使用标准的 LINQ 查询,相关实体将加载为 NULL
更新
我现在收到一个无效列错误 - 我注意到在我之前的代码中我没有在 brand
的 ICollection 上使用 virtual现在我不明白为什么它会在 SQL
中生成 EventId1 列EF 7 版本为 1.0.0-rc1-final
UPDATE-2 在使用代码后,异常在代码中变为循环依赖异常,代码与上面完全相同——我不知道为什么它早些时候生成了无效的列名 (EventId1)
在这里回答我自己的问题 - 弄明白了 -
这里使用的 2 个实体,我在 EF 7 中使用了完全定义的关系 - 然而 JSON 序列化程序不喜欢那样,因为这会产生循环依赖 - 品牌包含事件列表,并且每个事件还包含父品牌 属性 -
所以这里的解决方案是将 [JsonIgnore] 属性添加到子项的关系属性中
更新事件 class:
[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; }
}