1
votes

I have a very complex database model. My program computes some data+db entries and modifies+generates new entries to update+insert in the database.

When I use database context to insert the entries, everything works. But when I try to save changes:

{"The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable. When a change is made to a relationship, the related foreign-key property is set to a null value. If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted."}

I have seen too many questions on SO about this topic. But my problem is that the model is so complex that I cannot track the issue. Entity Framework 6 is not giving me any information about the source of the problem, relationship name, ...

Is there a way to get more help from Entity Framework in order to find the source of the problem?

3

3 Answers

1
votes

You have to analyze your object to solve this problem.

Here some simple code to explain your Exception:

static void Main()
{
    using (MyDbContext ctx = new MyDbContext())
    {
        // Build a new object
        MyClass o = new MyClass() { Id = 1, ChildObject = null };

        // Add it to your Context (It's not in the DB yet!)
        ctx.MyObjects.Add(o);

        // Write all changes (the new object) to the Db
        ctx.SaveChanges();
    }
}

// You got some DbContext with a DbSet pointing to your Table "MyTable"
public class MyDbContext : DbContext
{
    public DbSet<MyClass> MyObjects { get; set; }
}

// You've got a class to map your table to some nice object.
[Table("MyTable")]
public class MyClass
{
    // Some column..
    [Key]
    public int Id { get; set; }

    // And some ForeignKey! Which maps a column with the Id to an object.
    [ForeignKey("ChildObjectId")]
    public MyClass ChildObject { get; set; }
}

In this example i create a Context add an object and save the changes (create an Insert to the table).

1st: The Exception occurs at SaveChanges, because the Property "ChildObject" can be set to null, becuase we don't have any restrictions on that property.

2nd: The Exception is a Db-Exception. Your Program is (probably) runnging correct. But qour Db tells you, that it is not allowed to have a row in MyTable without a reference to a ChildObject.

You have to question yourself if the db is configured wrong (Make the column nullable) or if your program forgets to set the child.

I hope you see: You have to dig in your code. You got a problem with your 'complet model' and you have to solve it.

Consider reading the SQL-Log of the context. Example: ctx.Log = Console.WriteLine; (Don't have a Studio here, but i think i should be something like this).

This way you can grab the last SQL-Query and run it on your Db for better error-outputs.

0
votes

Issue is occurring because referenced table values are associated to the main table directly inside the c# object of Main table

CREATE TABLE [dbo].[MainTable](
            [MainId] [int],
            [Name] [varchar](50) NOT NULL
);

CREATE TABLE [dbo].[ReferedTable](
            [ReferId] [int],
            [MainId] [int] NOT NULL,
            [Name] [varchar](50) NULL
);

And there is constraint on the foreign key

using (EF context = new EF())
{
        var values = context.MainTable.Include("ReferedTable");
        var referedValues = values.ReferedTable.ToList();

        foreach (var value in referedValues)
        {
            context.ReferedTable.DeleteObject(value);
        }
        context.SaveChanges();
}

If you try to do below, then error will come. Because ReferedTable is connected to Main table and if you do changes in it and save, EF will throw error

using (EF context = new EF())
{
        var values = context.MainTable.Include("ReferedTable");
        var referedValues = values.ReferedTable.ToList();

        foreach (var value in referedValues)
        {
            values.ReferedTable.Remove(value);
        }
        context.SaveChanges();
}
0
votes

I manually went recursively for each child of my object doing this procedure:

if(parent.child!=null){
    parent.childId=parent.child.id;
    parent.child=null;
}

By this way you remove every child object from parent and just leave the Id, so EntityFramework does not make any wrong insertion and it is still conscient that the relationships exist.