简体   繁体   English

实体框架冲突外键约束

[英]Entity Framework conflicting foreign key constraint

I'm currently working on a website project which has a Repository as a separate project written in c# using Entity Framework which I have never used before. 我目前正在处理一个网站项目,该项目具有一个存储库,它是一个使用c#编写的独立项目,使用的是我从未使用过的Entity Framework。 I'm having an issue whereby if I try to add a new vessel via the front end when running im getting a database error. 我遇到一个问题,如果我在运行时遇到数据库错误,尝试通过前端添加新容器。

I've spent a day looking into why this isn't working, and finally decided I must ask the question. 我花了一天的时间研究为什么它不起作用,最后决定我必须提出这个问题。 I've looked at a lot of already asked questions on this but none of them have helped me. 我已经看过很多已经问过的问题,但是没有一个对我有帮助。

Im using Entity Framework, and currently having trouble adding a 'Vessel' to the database due to a foreign key constraint. 我正在使用实体框架,由于外键约束,目前无法在数据库中添加“容器”。

Code

VesselRepository.cs 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);
            }
        }

This is the method that the error occurs on, specifically on the SaveChanges() line, with the following message: 这是发生错误的方法,特别是在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."

These are the VesselConfiguration.cs & AttachmentConfiguration.cs files: 这些是VesselConfiguration.csAttachmentConfiguration.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");

        }
    }

At database level this is the structure im using for the Attachment and Vessel tables: 在数据库级别,这是用于Attachment表和Vessel表的结构:

在此处输入图片说明

And finally this is the BoatContext class: 最后是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);
        }

    }

I understand that the error message is telling me that I'm trying to insert a record into the Vessel table when the foreign key does not exist in the Attachment table, however the vesselId in the Vessel table has Identity Specification , so when I debug and inspect the vesselId it is always set to zero before the insert. 我了解错误消息告诉我,当附件表中不存在外键时,我正在尝试将记录插入Vessel表中,但是Vessel表中的vesselId具有Identity Specification ,因此在调试和在插入之前检查vesselId是否始终设置为零。

Things I've tried 我尝试过的事情

Tried adding dbContext.Attachments.Add(newVessel.Attachment); 尝试添加dbContext.Attachments.Add(newVessel.Attachment); before the SaveChanges() but got the same error, I've tried adding HasOptional(vsl => vsl.Attachment).WithRequired(attment => attment.Vessel); SaveChanges()之前但出现相同的错误,我尝试添加HasOptional(vsl => vsl.Attachment).WithRequired(attment => attment.Vessel); to the VesselConfiguration.cs but this made no difference, I've also tried setting the vesselId to null but got a error as vesselId cannot be null. VesselConfiguration.cs但这没有什么区别,我也尝试将vesselId设置为null但是由于vesselId不能为null而出现错误。

I have also run SQL Profiler and with some test data taken from the front end the query which failed with the above error was: 我还运行了SQL事件探查器,并从前端获取了一些测试数据,但由于上述错误而失败的查询是:

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

When I inspect the newVessel object prior to the save everything looks in order, the Vessel data that I entered is all present, the attachment details are all there, even the PersonId matches the already present record in the Person table, the only thing that is off is the VesselId , but I assumed this would be handled by SQL Server on the insert. 当我在保存所有内容之前按顺序检查newVessel对象时,输入的Vessel数据全部存在,附件详细信息全部存在,即使PersonId与Person表中已经存在的记录匹配,唯一的问题是关闭是VesselId ,但是我假设这将由插入中的SQL Server处理。 Its as if it isn't doing anything with the Attachment information it has in memory but the Attachment class is a property of Vessel : 好像它对内存中的Attachment信息没有做任何事情,但是Attachment类是Vessel的属性:

public class Vessel
{
    public int VesselId { get; set; }
    public int PersonId { get; set; }
    public string VesselName { get; set; }
    public string ClassType { get; set; }
    public string Makemodel { get; set; }
    public string Length { get; set; }
    public string Construction { get; set; }
    public string HullColour { get; set; }
    public string EngineTypeHP { get; set; }
    public string DataTagNumber { get; set; }
    public string MMSINumber { get; set; }
    public bool ArchiveStatus { get; set; }
    public string PermitNumber { get; set; }
    public string RegistrationNumber { get; set; }

    public virtual Person Person { get; set; }
    public virtual Attachment Attachment { get; set; }
}

The way you use Entity Framework is a whole lot different than the way I use it. 您使用实体框架的方式与我使用它的方式有很大不同。 I can't really tell what the problem is causing with your way but you are right on one thing. 我不能说出问题到底是什么原因造成的,但您是正确的。 Entity framework should create an ID for you when executing it's SQL. 实体框架在执行SQL时应为您创建一个ID。

Anyway you can try this if nothing else works. 无论如何,如果没有其他方法,您可以尝试此操作。

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);
        }
    }

I think the problem here lies within your database schema. 我认为这里的问题出在您的数据库架构内。

Column VesselId is configured as primary key in Table 'Attachments', however it should be used as a foreign key as well, that references the 'VesselId' column of table Vessel. 在表“附件”中,列VesselId被配置为主键,但是,它也应用作外键,它引用了表Vessel的“ VesselId”列。

Column 'VesselId' in table 'Vessel' on the other hand, should be renamed to 'Id' and used only as primary key, definitely not as a foreign key. 另一方面,表“ Vessel”中的“ VesselId”列应重命名为“ Id”,并且仅用作主键,绝对不能用作外键。

Adding a new Vessel entity is not possible in your case, as your foreign key constraint in table 'Vessel' checks whether an entry with VesselId exists in table 'Attachment', but that's not the case. 根据您的情况,您无法添加新的Vessel实体,因为表'Vessel'中的外键约束会检查表'Attachment'中是否存在带有VesselId的条目,但事实并非如此。

Hope this helps. 希望这可以帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM