依赖角色具有多个具有不同值的主体

时间:2013-03-18 14:39:26

标签: c# entity-framework

我正在使用Enitity Framework代码,我有以下设计

public class Location
{
    public int Id { get; set; }
    public string Name { get; set; }
    public bool IsDeleted { get; set; }
}

public class DelieryRate 
{
    public int Id { get; set; }

    public int OriginId { get; set; }
    public Location Origin { get; set; }

    public int DestinationId { get; set; }
    public Location Destination { get; set; }

    public double Amount { get; set; }

    public bool IsActive { get; set; }
}

我不想在Location上定义关系。当我更新数据库时,它可以工作,但是当我运行种子代码时,我得到了参照完整性错误。我尝试使用流畅的api配置它,如下所示

modelBuilder.Entity<DeliveryRate>()
            .HasRequired(e => e.Origin)
            .WithOptional()
            .WillCascadeOnDelete(false);

modelBuilder.Entity<DeliveryRate>()
            .HasRequired(e => e.Destination)
            .WithOptional()
            .WillCascadeOnDelete(false);

尝试更新数据库时出现以下错误

  

System.Data.Entity.Infrastructure.DbUpdateException:更新条目时发生错误。有关详细信息,请参阅内部异常---&GT; System.Data.UpdateException:更新条目时发生错误。有关详细信息,请参阅内部异常---&GT; System.Data.ConstraintException:参照完整性约束违规。依赖角色具有多个具有不同值的主体。      ---内部异常堆栈跟踪结束---      在System.Data.Mapping.Update.Internal.TableChangeProcessor.DiagnoseKeyCollision(UpdateCompiler编译器,PropagatorResult更改,CompositeKey键,PropagatorResult其他)      在System.Data.Mapping.Update.Internal.TableChangeProcessor.ProcessKeys(UpdateCompiler编译器,列出1 changes, Set 1个键)      在System.Data.Mapping.Update.Internal.TableChangeProcessor.CompileCommands(ChangeNode changeNode,UpdateCompiler编译器)      在System.Data.Mapping.Update.Internal.UpdateTranslator.d__0.MoveNext()      在System.Linq.Enumerable.d__71 1.MoveNext() at System.Data.Mapping.Update.Internal.UpdateCommandOrderer..ctor(IEnumerable 1个命令,UpdateTranslator翻译器)      在System.Data.Mapping.Update.Internal.UpdateTranslator.ProduceCommands()      在System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager stateManager,IEntityAdapter adapter)      在System.Data.EntityClient.EntityAdapter.Update(IEntityStateManager entityCache)      在System.Data.Objects.ObjectContext.SaveChanges(SaveOptions选项)      在System.Data.Entity.Internal.InternalContext.SaveChanges()      ---内部异常堆栈跟踪结束---      在System.Data.Entity.Internal.InternalContext.SaveChanges()      在System.Data.Entity.Internal.LazyInternalContext.SaveChanges()      在System.Data.Entity.DbContext.SaveChanges()      在System.Data.Entity.Migrations.DbMigrator.SeedDatabase()      在System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.SeedDatabase()      在System.Data.Entity.Migrations.DbMigrator.Upgrade(IEnumerable 1 pendingMigrations, String targetMigrationId, String lastMigrationId) at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.Upgrade(IEnumerable 1 pendingMigrations,String targetMigrationId,String lastMigrationId)      在System.Data.Entity.Migrations.DbMigrator.Update(String targetMigration)      在System.Data.Entity.Migrations.Infrastructure.MigratorBase.Update(String targetMigration)      在System.Data.Entity.Migrations.Design.ToolingFacade.UpdateRunner.RunCore()      在System.Data.Entity.Migrations.Design.ToolingFacade.BaseRunner.Run()   更新条目时发生错误。有关详细信息,请参阅内部异常

是否有更好的方法来模拟Locations和DeliveryRate之间的关系。 我是否用流利的api位错误

2 个答案:

答案 0 :(得分:4)

Entity Framework不支持与单独外键的一对一关系。 EF使用共享主键映射模型,DeliveryRate.IdDeliveryRate.Origin.IdDeliveryRate.Destination.Id必须具有相同的值。它们可能不在您的Seed方法中,这是异常的原因。

共享主键对您的模型无用,因为您永远无法创建DeliveryRateDestination不同的Origin

您可以通过将两个关系建模为一对多来解决问题:

modelBuilder.Entity<DeliveryRate>()
    .HasRequired(e => e.Origin)
    .WithMany()
    .HasForeignKey(e => e.OriginId)
    .WillCascadeOnDelete(false);

modelBuilder.Entity<DeliveryRate>()
    .HasRequired(e => e.Destination)
    .WithMany()
    .HasForeignKey(e => e.DestinationId)
    .WillCascadeOnDelete(false);

答案 1 :(得分:0)

当关系映射出错时,会引发此错误,它可能是将两个关系映射到相同的外键属性:

modelBuilder.Entity<TipOrder>().HasRequired(c => c.Tip).WithMany(x => x.TipOrders).HasForeignKey(x => x.TipId).WillCascadeOnDelete(false);
modelBuilder.Entity<TipOrder>().HasRequired(c => c.Order).WithMany(x => x.TipOrders).HasForeignKey(x => x.TipId).WillCascadeOnDelete(false);

两者都意外地映射到TipId。