ef/breeze("Unable to determine a valid ordering")如何指定两个导航关系?
How to specify two navigation relations for ef/breeze ("Unable to determine a valid ordering")?
我从两个方面尊重一个实体"monitoring":
- 作为公司监控列表的一部分
- 作为公司的主动(=当前选择)监控
public class Company
{
[Key]
[DataMember]
public virtual Guid CompanyId { get; set; }
[DataMember]
public virtual Guid? MonitoringId { get; set; }
[DataMember]
[ForeignKey("MonitoringId")]
public virtual Monitoring ActiveMonitoring { get; set; }
[DataMember]
public virtual ICollection<Monitoring> Monitorings { get; set; }
}
public class Monitoring
{
[Key]
[DataMember]
public virtual Guid MonitoringId { get; set; }
[DataMember]
public virtual Guid CompanyId { get; set; }
[DataMember]
[ForeignKey("CompanyId")]
public virtual Company Company { get; set; }
}
如果我创建一个新的公司并在监控列表中添加一个新的监控,我可以轻而易举地保存它。保存新公司后,我可以将已添加的监控设置为 ActiveMonitoring 并再次保存公司。
但是,如果我尝试添加监控 和 并将其设置为 ActiveMonitioring 并只保存公司一次,我会收到以下错误:
Unable to determine a valid ordering for dependent operations.
Dependencies may exist due to foreign key constraints, model
requirements, or store-generated values.
下面是创建新公司的示例 JavaScript 代码:
var company = unitofwork.companyRepository.create();
var monitoring = unitofwork.monitoringRepository.create();
//add monitoring to the list of monitorings
monitoring.company(company);
company.monitorings.push(monitoring);
//set monitoring as active monitoring
company.activeMonitoring(monitoring);
unitofwork.commit();
我使用 EntityFramework 6 和 Breeze 1.5.4
我尝试使用注解"InverseProperty"使关系更明确但没有成功。我还发现了一些相关的 Whosebug 问题,但我找不到针对我的特定问题的解决方案:
more than one navigation to the same entity
Unable to determine a valid ordering for dependent operations
How to specify two navigation properties from entity X to the same target entity, Y?
我的 类 允许以下情况:监控可以是一家公司列表的一部分,并被设置为另一家公司的活动监控。但是,我不想允许这种情况:只有当监控也是同一公司的监控列表的一部分时,才应允许它成为主动监控。这是我问题的根本原因吗?
监控是否需要两次提及公司,例如CompanyForListReference 和 CompanyForActiveReference?或者是否有只适用于一个 CompanyId 的解决方案?
我也想过不把一个实例保存为活跃的监控,而是在监控列表中只保存活跃监控的索引,例如"IndexOfActiveMonitoring"。但是,如果我想访问活动监控,我需要一些额外的代码来查找活动监控。
=> 实施从公司到监控的两个引用的推荐方法是什么?
我只能说Entity Framework这一部分,但总体问题是一样的。出现此问题是因为命令的顺序很奇怪,您需要 运行 才能添加行 - 不可能一步完成。您需要插入公司行(您可以同时添加监控列表),然后调用 savechanges。这会生成实体的 ID,然后您可以使用这些来更新相关 ID。
EF 不够聪明,无法了解在单个实体上执行多项操作,在这些情况下,您需要使用显式事务并多次调用 SaveChanges。使用 EF-only,这将类似于:
using (var trans = new TransactionScope())
{
Company company = new Company(); // ... populate
company.Monitorings.Add(new Monitoring());
company.Monitorings.Add(new Monitoring());
context.Companies.Add(company);
context.SaveChanges();
company.ActiveMonitoring = company.Monitorings.First();
context.SaveChanges();
trans.Complete()
}
我已经修改了你的类,做了一个示例代码,结果成功了:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
namespace TestApp
{
public class Company
{
[Key]
public virtual Guid CompanyId { get; set; }
public virtual Guid? MonitoringId { get; set; }
[ForeignKey("MonitoringId")]
[InverseProperty("Companies")]
public virtual Monitoring ActiveMonitoring { get; set; }
[InverseProperty("Company")]
public virtual ICollection<Monitoring> Monitorings { get; set; }
}
public class Monitoring
{
[Key]
public virtual Guid MonitoringId { get; set; }
public virtual Guid CompanyId { get; set; }
[ForeignKey("CompanyId")]
[InverseProperty("Monitorings")]
public virtual Company Company { get; set; }
[InverseProperty("ActiveMonitoring")]
public virtual ICollection<Company> Companies { get; set; }
}
public class DatabaseContext : DbContext
{
public DatabaseContext() : base("TestContext")
{
}
public DbSet<Company> Companies { get; set; }
public DbSet<Monitoring> Monitorings { get; set; }
}
class Program
{
static void Main(string[] args)
{
Company cmp = new Company();
cmp.CompanyId = Guid.NewGuid();
using (var db = new DatabaseContext())
{
db.Companies.Add(cmp);
db.Monitorings.Add(new Monitoring { CompanyId = cmp.CompanyId, MonitoringId = Guid.NewGuid() });
db.Monitorings.Add(new Monitoring { CompanyId = cmp.CompanyId, MonitoringId = Guid.NewGuid() });
var m1 = new Monitoring { CompanyId = cmp.CompanyId, MonitoringId = Guid.NewGuid() };
db.Monitorings.Add(m1);
db.Companies.Add(new Company { CompanyId = Guid.NewGuid() ,MonitoringId = m1.MonitoringId });
db.SaveChanges();
}
}
}
}
我从两个方面尊重一个实体"monitoring":
- 作为公司监控列表的一部分
- 作为公司的主动(=当前选择)监控
public class Company
{
[Key]
[DataMember]
public virtual Guid CompanyId { get; set; }
[DataMember]
public virtual Guid? MonitoringId { get; set; }
[DataMember]
[ForeignKey("MonitoringId")]
public virtual Monitoring ActiveMonitoring { get; set; }
[DataMember]
public virtual ICollection<Monitoring> Monitorings { get; set; }
}
public class Monitoring
{
[Key]
[DataMember]
public virtual Guid MonitoringId { get; set; }
[DataMember]
public virtual Guid CompanyId { get; set; }
[DataMember]
[ForeignKey("CompanyId")]
public virtual Company Company { get; set; }
}
如果我创建一个新的公司并在监控列表中添加一个新的监控,我可以轻而易举地保存它。保存新公司后,我可以将已添加的监控设置为 ActiveMonitoring 并再次保存公司。
但是,如果我尝试添加监控 和 并将其设置为 ActiveMonitioring 并只保存公司一次,我会收到以下错误:
Unable to determine a valid ordering for dependent operations. Dependencies may exist due to foreign key constraints, model requirements, or store-generated values.
下面是创建新公司的示例 JavaScript 代码:
var company = unitofwork.companyRepository.create();
var monitoring = unitofwork.monitoringRepository.create();
//add monitoring to the list of monitorings
monitoring.company(company);
company.monitorings.push(monitoring);
//set monitoring as active monitoring
company.activeMonitoring(monitoring);
unitofwork.commit();
我使用 EntityFramework 6 和 Breeze 1.5.4
我尝试使用注解"InverseProperty"使关系更明确但没有成功。我还发现了一些相关的 Whosebug 问题,但我找不到针对我的特定问题的解决方案:
more than one navigation to the same entity
Unable to determine a valid ordering for dependent operations
How to specify two navigation properties from entity X to the same target entity, Y?
我的 类 允许以下情况:监控可以是一家公司列表的一部分,并被设置为另一家公司的活动监控。但是,我不想允许这种情况:只有当监控也是同一公司的监控列表的一部分时,才应允许它成为主动监控。这是我问题的根本原因吗?
监控是否需要两次提及公司,例如CompanyForListReference 和 CompanyForActiveReference?或者是否有只适用于一个 CompanyId 的解决方案?
我也想过不把一个实例保存为活跃的监控,而是在监控列表中只保存活跃监控的索引,例如"IndexOfActiveMonitoring"。但是,如果我想访问活动监控,我需要一些额外的代码来查找活动监控。
=> 实施从公司到监控的两个引用的推荐方法是什么?
我只能说Entity Framework这一部分,但总体问题是一样的。出现此问题是因为命令的顺序很奇怪,您需要 运行 才能添加行 - 不可能一步完成。您需要插入公司行(您可以同时添加监控列表),然后调用 savechanges。这会生成实体的 ID,然后您可以使用这些来更新相关 ID。
EF 不够聪明,无法了解在单个实体上执行多项操作,在这些情况下,您需要使用显式事务并多次调用 SaveChanges。使用 EF-only,这将类似于:
using (var trans = new TransactionScope())
{
Company company = new Company(); // ... populate
company.Monitorings.Add(new Monitoring());
company.Monitorings.Add(new Monitoring());
context.Companies.Add(company);
context.SaveChanges();
company.ActiveMonitoring = company.Monitorings.First();
context.SaveChanges();
trans.Complete()
}
我已经修改了你的类,做了一个示例代码,结果成功了:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
namespace TestApp
{
public class Company
{
[Key]
public virtual Guid CompanyId { get; set; }
public virtual Guid? MonitoringId { get; set; }
[ForeignKey("MonitoringId")]
[InverseProperty("Companies")]
public virtual Monitoring ActiveMonitoring { get; set; }
[InverseProperty("Company")]
public virtual ICollection<Monitoring> Monitorings { get; set; }
}
public class Monitoring
{
[Key]
public virtual Guid MonitoringId { get; set; }
public virtual Guid CompanyId { get; set; }
[ForeignKey("CompanyId")]
[InverseProperty("Monitorings")]
public virtual Company Company { get; set; }
[InverseProperty("ActiveMonitoring")]
public virtual ICollection<Company> Companies { get; set; }
}
public class DatabaseContext : DbContext
{
public DatabaseContext() : base("TestContext")
{
}
public DbSet<Company> Companies { get; set; }
public DbSet<Monitoring> Monitorings { get; set; }
}
class Program
{
static void Main(string[] args)
{
Company cmp = new Company();
cmp.CompanyId = Guid.NewGuid();
using (var db = new DatabaseContext())
{
db.Companies.Add(cmp);
db.Monitorings.Add(new Monitoring { CompanyId = cmp.CompanyId, MonitoringId = Guid.NewGuid() });
db.Monitorings.Add(new Monitoring { CompanyId = cmp.CompanyId, MonitoringId = Guid.NewGuid() });
var m1 = new Monitoring { CompanyId = cmp.CompanyId, MonitoringId = Guid.NewGuid() };
db.Monitorings.Add(m1);
db.Companies.Add(new Company { CompanyId = Guid.NewGuid() ,MonitoringId = m1.MonitoringId });
db.SaveChanges();
}
}
}
}