实体框架冲突外键约束

时间:2014-07-01 15:37:55

标签: c# entity-framework sql-server-2008

我目前正在开发一个网站项目,它将一个Repository作为一个单独的项目,用c#编写,使用我以前从未使用过的Entity Framework。我遇到了一个问题,如果我在运行时遇到数据库错误,尝试通过前端添加新容器。

我花了一天时间研究为什么这不起作用,最后决定我必须问这个问题。我已经看了很多已经问过的问题,但没有一个帮助过我。

我正在使用Entity Framework,由于外键约束,目前无法在数据库中添加“Vessel”。

代码

VesselRepository.cs

public int CreateVessel(Vessel newVessel)
        {
            using (BoatContext dbContext = new BoatContext())
            {
                dbContext.Vessels.Add(newVessel);                   
                dbContext.SaveChanges();

                //return new vessel id
                return Convert.ToInt32(newVessel.VesselId);
            }
        }

这是发生错误的方法,特别是在SaveChanges()行上,并带有以下消息:

"The INSERT statement conflicted with the FOREIGN KEY constraint "FK_Vessel_Attachment1". The conflict occurred in database "BoatRegistration", table "dbo.Attachment", column 'VesselId'.
The statement has been terminated."

这些是VesselConfiguration.cs& AttachmentConfiguration.cs个文件:

public class VesselConfiguration :EntityTypeConfiguration<Vessel>
{
    public VesselConfiguration()
        : base()
    {

        HasKey(v => v.VesselId);
        ToTable("Vessel");           

    }
}

class AttachmentConfiguration : EntityTypeConfiguration<Attachment>
    {
        public AttachmentConfiguration()
            : base()
        {
            HasKey(a => a.VesselId);

            HasRequired(attment => attment.Vessel).WithOptional(vsl => vsl.Attachment);

            ToTable("Attachment");

        }
    }

在数据库级别,这是我用于AttachmentVessel表的结构:

enter image description here

最后这是 BoatContext 类:

public class BoatContext : DbContext
    {
        public DbSet<Person> Persons { get; set; }
        public DbSet<Vessel> Vessels { get; set; }
        public DbSet<Club> Clubs { get; set; }
        public DbSet<Attachment> Attachments { get; set; }


        public BoatContext()
            : base("Name=BoatRegistrationConnectionString")
        {
            System.Data.Entity.Database.SetInitializer<BoatContext>(null);
        }

        protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
        {
            modelBuilder.Configurations.Add(new PersonConfiguration());
            modelBuilder.Configurations.Add(new VesselConfiguration());
            modelBuilder.Configurations.Add(new ClubConfiguration());
            modelBuilder.Configurations.Add(new AttachmentConfiguration());
            base.OnModelCreating(modelBuilder);
        }

    }

我理解错误消息告诉我,当附件表中不存在外键时,我正在尝试将记录插入到Vessel表中,但是Vessel表中的vesselId具有{ {1}},所以当我调试并检查Identity Specification时,它总是在插入之前设置为零。

我尝试过的事情

尝试在vesselId之前添加dbContext.Attachments.Add(newVessel.Attachment);但收到同样的错误,我尝试将SaveChanges()添加到HasOptional(vsl => vsl.Attachment).WithRequired(attment => attment.Vessel);,但这没有任何区别,我也是尝试将VesselConfiguration.cs设置为vesselId,但收到错误,因为null不能为空。

我还运行了SQL事件探查器,并且从前端获取的一些测试数据导致上述错误失败的查询是:

vesselId

当我在保存之前检查exec sp_executesql N'INSERT [dbo].[Vessel]([PersonId], [VesselName], [ClassType], [Makemodel], [Length], [Construction], [HullColour], [EngineTypeHP], [DataTagNumber], [MMSINumber], [ArchiveStatus], [PermitNumber], [RegistrationNumber]) VALUES (@0, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, NULL, NULL) SELECT [VesselId] FROM [dbo].[Vessel] WHERE @@ROWCOUNT > 0 AND [VesselId] = scope_identity()',N' @0 int,@1 nvarchar(max) ,@2 nvarchar(max) ,@3 nvarchar(max) , @4 nvarchar(max) ,@5 nvarchar(max) ,@6 nvarchar(max) ,@7 nvarchar(max) , @8 nvarchar(max) ,@9 nvarchar(max) ,@10 bit', @0=27,@1=N'dgfgdf',@2=N'dfgdf',@3=N'dgfgdf',@4=N'34534',@5=N'dfgdfg', @6=N'dgfgf',@7=N'43534543',@8=N'5433',@9=N'33445',@10=0 对象时,所有内容都按顺序查看,我输入的船只数据全部存在,附件详细信息全部存在,即使newVessel匹配已存在记录在Person表中,唯一关闭的是PersonId,但我认为这将由插件上的SQL Server处理。就好像它没有对内存中的VesselId信息做任何事情,但Attachment类是Attachment的属性:

Vessel

2 个答案:

答案 0 :(得分:0)

使用Entity Framework的方式与我使用它的方式有很大不同。 我无法确定问题是由你的方式引起的,但你是对的。实体框架应该在执行SQL时为您创建一个ID。

无论如何,如果没有别的办法,你可以试试这个。

public int CreateVessel(Vessel newVessel)
    {
        using (BoatContext dbContext = new BoatContext())
        {
            newVessel.VesselId = new Vessel().VesselId;
            //newVessel.Attachment = null
            // OR
            //Attachment attach = new Attachment();
            //newVessel.Attachement = attach;

            dbContext.Vessels.Add(newVessel);                   
            dbContext.SaveChanges();

            //return new vessel id
            return Convert.ToInt32(newVessel.VesselId);
        }
    }

答案 1 :(得分:0)

我认为这里的问题在于您的数据库架构。

列VesselId在表'Attachments'中被配置为主键,但它也应该用作外键,它引用表Vessel的'VesselId'列。

另一方面,表'Vessel'中的'VesselId'列应重命名为'Id'并仅用作主键,绝对不能用作外键。

在您的情况下,无法添加新的Vessel实体,因为表'Vessel'中的外键约束会检查表'Attachment'中是否存在包含VesselId的条目,但情况并非如此。

希望这有帮助。