Entity Framework: одно или несколько свойств внешнего ключа не обнуляются - PullRequest
0 голосов
/ 28 августа 2018

У меня очень сложная модель базы данных. Моя программа вычисляет некоторые data+db entries и modifies+generates new entries для обновления + вставки в базу данных.

Когда я использую контекст базы данных для вставки записей, все работает. Но когда я пытаюсь сохранить изменения:

{"Операция завершилась неудачно: отношение не может быть изменено, так как одно или несколько свойств внешнего ключа не могут быть равны нулю. Когда в отношение вносится изменение, для связанного свойства внешнего ключа устанавливается значение NULL. значение. Если внешний ключ не поддерживает нулевые значения, необходимо определить новое отношение, свойству внешнего ключа должно быть присвоено другое ненулевое значение или не связанный объект должен быть удален. "}

Я видел слишком много вопросов на SO по этой теме. Но моя проблема в том, что модель настолько сложна, что я не могу отследить проблему. Entity Framework 6 не предоставляет мне никакой информации об источнике проблемы, имени отношения, ...

Есть ли способ получить дополнительную помощь от Entity Framework, чтобы найти источник проблемы?

Ответы [ 3 ]

0 голосов
/ 28 августа 2018

Проблема возникает из-за того, что ссылочные значения таблицы связаны с основной таблицей непосредственно внутри объекта c # главной таблицы

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

И есть ограничение на внешний ключ

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

Если вы попытаетесь сделать ниже, то придет ошибка. Поскольку ReferedTable подключен к главной таблице, и если вы внесете в нее изменения и сохраните ее, EF выдаст ошибку

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 голосов
/ 28 августа 2018

Я вручную пошел рекурсивно для каждого потомка моего объекта, выполняя эту процедуру:

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

Таким образом вы удаляете каждый дочерний объект из родительского и просто оставляете Id, поэтому EntityFramework не делает неправильных вставок, и все еще очевидно, что отношения существуют.

0 голосов
/ 28 августа 2018

Вы должны проанализировать свой объект, чтобы решить эту проблему.

Вот простой код для объяснения вашего 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; }
}

В этом примере я создаю Контекст, добавляю объект и сохраняю изменения (создаю Вставку в таблицу).

1-е: Исключение возникает в SaveChanges, поскольку для свойства "ChildObject" может быть установлено значение null, поскольку у нас нет никаких ограничений на это свойство.

2-й: Исключением является Db-исключение. Ваша Программа (вероятно) работает правильно. Но qour Db говорит вам, что в MyTable нельзя иметь строку без ссылки на ChildObject.

Вы должны спросить себя, правильно ли сконфигурирована БД (сделать столбец обнуляемым) или ваша программа забудет установить дочерний элемент.

Я надеюсь, вы видите: вы должны копаться в своем коде. У вас проблема с «полной моделью», и вам нужно ее решить.

Рассмотрите возможность чтения SQL-журнала контекста. Пример: ctx.Log = Console.WriteLine; (У меня здесь нет студии, но я думаю, что должен быть примерно таким).

Таким образом, вы можете получить последний SQL-запрос и запустить его на своей базе данных для лучшего вывода ошибок.

...