简体   繁体   中英

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. 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

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:

"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:

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:

在此处输入图片说明

And finally this is the BoatContext class:

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.

Things I've tried

Tried adding 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); 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.

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:

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. 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 :

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.

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.

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.

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.

Hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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