如果我不删除OneToManyCascadeDeleteConvention,实体框架会抛出System.NullReferenceException

时间:2013-08-11 09:20:19

标签: entity-framework entity-framework-5

以下是我正在尝试做的示例代码,我正在获取NullReferenceException。如果我删除OneToManyCascadeDeleteConvention,那么一切正常。谁能帮助我理解这里的问题。

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

public class Post
{
    public Post()
    {
        this.Messages = new HashSet<Message>();
        this.PostHistories = new HashSet<PostHistory>();
    }

    public int Id { get; set; }

    [Required]
    public int MessageBoardId { get; set; }

    public virtual MessageBoard MessageBoard { get; set; }

    public virtual ICollection<Message> Messages { get; set; }
    public virtual ICollection<PostHistory> PostHistories { get; set; }
}

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

    [Required]
    public int PostId { get; set; }

    public virtual Post Post { get; set; }

    public virtual ICollection<MessageHistory> MessageHistories { get; set; }
}

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

    [Required]
    public int MessageBoardId { get; set; }

    public virtual MessageBoard MessageBoard { get; set; }

    public virtual ICollection<PostHistory> PostHistories { get; set; }
}

public class PostHistory
{
    public PostHistory()
    {
        this.MessageHistories = new HashSet<MessageHistory>();
    }

    [Key, Column(Order = 0)]
    [ForeignKey("MessageBoardVersion")]
    public int MessageBoardVersionId { get; set; }

    [Key, Column(Order = 1)]
    [ForeignKey("Post")]
    public int PostId { get; set; }

    public virtual MessageBoardVersion MessageBoardVersion { get; set; }

    public virtual ICollection<MessageHistory> MessageHistories { get; set; }

    public virtual Post Post { get; set; }
}

public class MessageHistory
{
    [Key, Column(Order = 2)]
    [ForeignKey("Message")]
    public int MessageId { get; set; }

    [Key, Column(Order = 0)]
    [ForeignKey("PostHistory")]
    public int MessageBoardVersionId { get; set; }

    [Key, Column(Order = 1)]
    [ForeignKey("PostHistory")]
    public int PostId { get; set; }

    public virtual PostHistory PostHistory { get; set; }

    public virtual Message Message { get; set; }
}

public class MessageHistoryConfiguration : EntityTypeConfiguration<MessageHistory>
{
    public MessageHistoryConfiguration()
    {
        this.HasRequired(p => p.Message).WithMany(p => p.MessageHistories).WillCascadeOnDelete(false);
        this.HasRequired(p => p.PostHistory).WithMany(p => p.MessageHistories).WillCascadeOnDelete(true);
    }
}

public class PostHistoryConfiguration : EntityTypeConfiguration<PostHistory>
{
    public PostHistoryConfiguration()
    {
        this.HasRequired(p => p.MessageBoardVersion).WithMany(p => p.PostHistories).WillCascadeOnDelete(false);
    }
}

public class Model1Container : DbContext
{
    public Model1Container()
        : base("name=Model1Container")
    {
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {

        modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();

        /*
        *  
        * If I do Remove<OneToManyCascadeDeleteConvention> then code works fine
        */
        //modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
        //modelBuilder.Configurations.Add(new PostHistoryConfiguration());
        modelBuilder.Configurations.Add(new MessageHistoryConfiguration());
    }

    public DbSet<MessageBoard> MessageBoards { get; set; }
    public DbSet<Post> Posts { get; set; }
    public DbSet<Message> Messages { get; set; }
    public DbSet<MessageBoardVersion> MessageBoardVersions { get; set; }
    public DbSet<PostHistory> PostHistories { get; set; }
    public DbSet<MessageHistory> AnswerHistories { get; set; }
}

存在多个级联路径错误,因此如果我尝试在删除时禁用级联,则会出现以下异常

  

System.NullReferenceException未处理
  的HResult = -2147467261
  Message =对象引用未设置为对象的实例   来源=的EntityFramework
  堆栈跟踪:
  在System.Data.Entity.ModelConfiguration.Configuration.Types.EntityTypeConfiguration.Configure(EdmEntityType entityType,EdmModel model)
  在System.Data.Entity.ModelConfiguration.Configuration.ModelConfiguration.ConfigureEntities(EdmModel模型)
  在System.Data.Entity.ModelConfiguration.Configuration.ModelConfiguration.Configure(EdmModel模型)
  在System.Data.Entity.DbModelBuilder.Build(DbProviderManifest providerManifest,DbProviderInfo providerInfo)
  在System.Data.Entity.DbModelBuilder.Build(DbConnection providerConnection)
  在System.Data.Entity.Internal.LazyInternalContext.CreateModel(LazyInternalContext internalContext)
  在System.Data.Entity.Internal.RetryLazy`2.GetValue(TInput输入)
  在System.Data.Entity.Internal.LazyInternalContext.InitializeContext()
  在System.Data.Entity.Internal.InternalContext.CreateObjectContextForDdlOps()
  在System.Data.Entity.Database.Create(Boolean skipExistsCheck)
  在System.Data.Entity.Database.Create()
  在ConsoleApplication2.Program.Main(String [] args)中的c:\ Users \ dhawalh \ Documents \ Visual Studio 2012 \ Projects \ ConsoleApplication2 \ ConsoleApplication2 \ Program.cs:第160行
  在System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly,String [] args)
  在Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
  at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext,ContextCallback callback,Object state,Boolean preserveSyncCtx)
  at System.Threading.ExecutionContext.Run(ExecutionContext executionContext,ContextCallback callback,Object state,Boolean preserveSyncCtx)
  在System.Threading.ExecutionContext.Run(ExecutionContext executionContext,ContextCallback回调,对象状态)
  在System.Threading.ThreadHelper.ThreadStart()

如果删除OneToManyCascadeDeleteConvention ..

,我可以使代码工作的唯一方法
 modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();

我不确定为什么我得到空引用异常。有人可以帮忙吗?谢谢!

1 个答案:

答案 0 :(得分:0)

使用Fluent API(HasForeignKey)定义外键。

public MessageHistoryConfiguration()
{
    this.HasRequired(p => p.Message)
        .WithMany(p => p.MessageHistories)
        .HasForeignKey(p => p.MessageId)
        .WillCascadeOnDelete(false);

    //this.HasRequired(p => p.PostHistory)
    //    .WithMany(p => p.MessageHistories)
    //    .HasForeignKey(p => new { p.MessageBoardVersionId, p.PostId })
    //    .WillCascadeOnDelete(true);
}

第二个映射是多余的(因此我已将其注释掉)因为默认情况下所需的关系将默认进行级联删除。如果您确实要添加此映射,请包含HasForeignKey,如上所示,以使配置与数据注释相匹配。

PostHistoryConfiguration中的相同内容:

public PostHistoryConfiguration()
{
    this.HasRequired(p => p.MessageBoardVersion)
        .WithMany(p => p.PostHistories)
        .HasForeignKey(p => p.MessageBoardVersionId)
        .WillCascadeOnDelete(false);
}

OnModelCreating

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();

    modelBuilder.Configurations.Add(new PostHistoryConfiguration());
    modelBuilder.Configurations.Add(new MessageHistoryConfiguration());
}

对我来说,它无一例外地起作用。我不知道为什么会发生异常,它可能是EF中的一个错误。但另一方面,您的映射配置有点混乱,尤其是您使用Fluent API进行数据注释和(不完整)映射的混合。我会决定一个或另一个 - 至少每个实体,但最好是整个模型的Fluent API(因为在任何情况下都需要Fluent API才能禁用级联删除)。