EF Code First:多重约束违规

时间:2013-09-14 05:45:10

标签: c# entity-framework code-first fluent-interface

HELP! - 我的导航模型 ArticleType

收到以下错误
  

发生了关系多重性约束违规

以下是现有的数据库架构:

database model

这是我的代码:

public class Article
{
    public int ID { get; set; }
    public virtual Stage Stage { get; set; }
    public virtual ArticleType ArticleType { get; set; } // Causes the violation
}

public class ArticleType
{
    public int ID { get; set; }
    public string Title { get; set; }
}

public class Stage
{
    public int ID { get; set; }
    public string Title { get; set; }
}

我使用流畅的api进行映射,这是一个关联的摘录

// This works
modelBuilder.Entity<Article>
    .HasRequired(t => t.Stage)
    .WithMany() // if turned .WithOptional() then will also cause the error.
    .Map(m => m.MapKey("stage_id"));

// This does not work
modelBuilder.Entity<Article>
    .HasRequired(t => t.ArticleType)
    .WithMany()
    .Map(m => m.MapKey("article_type_id"));

我的问题是,为什么 ArticleType 导致错误但 Stage 不会,即使两者的声明和映射在语法上都相同?

编辑1

通过鼠标悬停检查文章对象(不确定确切的术语),我发现了异常

open image to new tabe

错误明细

System.InvalidOperationException was unhandled by user code
  HResult=-2146233079
  Message=A relationship multiplicity constraint violation occurred: An EntityReference can have no more than one related object, but the query returned more than one related object. This is a non-recoverable error.
  Source=System.Data.Entity
  StackTrace:
       at System.Data.Objects.DataClasses.EntityReference`1.Load(MergeOption mergeOption)
       at System.Data.Objects.DataClasses.RelatedEnd.Load()
       at System.Data.Objects.DataClasses.RelatedEnd.DeferredLoad()
       at System.Data.Objects.Internal.LazyLoadBehavior.LoadProperty[TItem](TItem propertyValue, String relationshipName, String targetRoleName, Boolean mustBeNull, Object wrapperObject)
       at System.Data.Objects.Internal.LazyLoadBehavior.<>c__DisplayClass7`2.<GetInterceptorDelegate>b__2(TProxy proxy, TItem item)
       at System.Data.Entity.DynamicProxies.Package_A18FADC105CCF13C9CD346622D43BD35514E489CCC1E5B1E4A3C78806BDCA0F5.get_ArticleType()
       at AuthorProofing.Service.ReminderService.DeliverDailyReminders() in C:\Users\default.Lenovo-PC\Documents\Visual Studio 2010\Projects\AuthorProofing\AuthorProofing.Service\ReminderService.cs:line 36
       at AuthorProofing.Tests.ReminderServiceTest.DeliverDailyRemindersTest() in C:\Users\default.Lenovo-PC\Documents\Visual Studio 2010\Projects\AuthorProofing\AuthorProofing.Tests\ReminderServiceTest.cs:line 76
  InnerException: 

编辑2

我决定选择明确的外键协会。

class ArticleMap : EntityTypeConfiguration<Article>
{
    public ArticleMap()
    {
        // Primary Key
        this.HasKey(t => t.ID);
        this.Property(t => t.ID)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

        // Strongly typed FK properties
        this.Property(t => t.StageID).IsRequired();
        this.Property(t => t.ArticleTypeID).IsRequired();

        // Navigation Models
        this.HasRequired(t => t.Stage);
        this.HasRequired(t => t.ArticleType);

        // Table & Column Mappings
        this.ToTable("items");
        this.Property(t => t.ID).HasColumnName("item_id");
        this.Property(t => t.StageID).HasColumnName("stage_id");
        this.Property(t => t.ArticleTypeID).HasColumnName("article_type_id");
    }
}


protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Configurations.Add(new ArticleTypeMap());
    modelBuilder.Configurations.Add(new StageMap());
    modelBuilder.Configurations.Add(new ArticleMap());
}

仍然无效。

使用新的外键映射方法,我尝试切换键 article_type_id stage_id

this.Property(t => t.StageID).HasColumnName("article_type_id"); // <-- Switched
this.Property(t => t.ArticleTypeID).HasColumnName("stage_id");  // <-- Switched

突然,错误消失了。目前困惑不解。我认为ArticleType模型不太喜欢外键“article_type_id”。

编辑3

在我的导航模型映射上添加.HasForeignKey(...)后,我收到了一个新错误:'字段列表'中的未知列'ArticleType_ID'

class ArticleMap : EntityTypeConfiguration<Article>
{
    public ArticleMap()
    {
        // Primary Key
        this.HasKey(t => t.ID);
        this.Property(t => t.ID)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

        // Foreign Key Properties
        this.Property(t => t.StageID)
            .IsRequired();
        this.Property(t => t.JournalID)
            .IsRequired();
        this.Property(t => t.ArticleTypeID)
            .IsRequired();

        // Navigational Models
        this.HasRequired(t => t.Stage); // This works
        this.HasRequired(t => t.ArticleType)
            .WithMany()
            .HasForeignKey(t => t.ArticleTypeID); // Newly added

        // Table & Column Mappings
        this.ToTable("items");
        this.Property(t => t.ID).HasColumnName("item_id");
        this.Property(t => t.ArticleTypeID).HasColumnName("article_type_id");
        this.Property(t => t.StageID).HasColumnName("stage_id");
    }
}

class ArticleTypeMap : EntityTypeConfiguration<ArticleType>
{
    public ArticleTypeMap()
    {
        // Primary Key
        this.HasKey(t => t.ID);

        // Properties
        this.Property(t => t.ID)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

        this.Property(t => t.Title)
            .HasMaxLength(100)
            .IsRequired();

        // Table & Column Mappings
        this.ToTable("article_types");
        this.Property(t => t.ID).HasColumnName("article_type_id"); // <-- Apparently, this is no longer mapped.
        this.Property(t => t.Title).HasColumnName("title");
    }
}

2 个答案:

答案 0 :(得分:9)

当搜索特定错误消息a时,其原因是错误地将一对多关系配置为一对一关系,使用:

modelBuilder.Entity<Article>
.HasRequired(t => t.ArticleType)
.WithOptional()
.HasForeignKey(...);

虽然它应该是:

modelBuilder.Entity<Article>
.HasRequired(t => t.ArticleType)
.WithMany()
.HasForeignKey(...);

您已经在自己的代码示例中指出了这一点。正如您为ArticleType显示的代码并且Stage是相同的,此代码是导致问题的原因没有意义。代码中的其他位置必须在ArticleArticleType之间定义一对一关系。或者以某种方式,你最初的关系是错误的,但实体框架没有提到纠正的流畅定义。

答案 1 :(得分:-4)

您可以从visual studio获取.edmx文件,并使用该文件映射您的数据库,以便根据数据库模式自动创建实体的关系映射。