简体   繁体   English

由于一个或多个外键属性不可为空,因此无法更改关系。 (2)

[英]The relationship could not be changed because one or more of the foreign-key properties is non-nullable. (2)

I'm using Entity Framework 6.1.3 in a .NET 4.5 application with Code First and a hand-crafted table schema on an Oracle database server.我在 .NET 4.5 应用程序中使用 Entity Framework 6.1.3,在 Oracle 数据库服务器上使用 Code First 和手工制作的表架构。 Most things work fine.大多数事情都运行良好。 For a new function the following exception is thrown in SaveChanges :对于新函数,在SaveChanges抛出以下异常:

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.如果外键不支持空值,则必须定义新关系,必须为外键属性分配另一个非空值,或者必须删除不相关的对象。

Stack trace:堆栈跟踪:

  • System.Data.Entity.Core.Objects.ObjectContext.PrepareToSaveChanges(System.Data.Entity.Core.Objects.SaveOptions) System.Data.Entity.Core.Objects.ObjectContext.PrepareToSaveChanges(System.Data.Entity.Core.Objects.SaveOptions)
  • System.Data.Entity.Core.Objects.ObjectContext.SaveChangesInternal(System.Data.Entity.Core.Objects.SaveOptions, bool) System.Data.Entity.Core.Objects.ObjectContext.SaveChangesInternal(System.Data.Entity.Core.Objects.SaveOptions, bool)
  • System.Data.Entity.Internal.InternalContext.SaveChanges() System.Data.Entity.Internal.InternalContext.SaveChanges()
  • (my code) (我的代码)

It says nothing about the problem.它没有说明问题。 It doesn't help me to find it.这对我找不到它没有帮助。 The SQL log is empty so I guess the problem was detected by EF locally before even trying to reach out to the database. SQL 日志是空的,所以我猜这个问题是在尝试访问数据库之前由 EF 在本地检测到的。

My question is: How can I debug this thing?我的问题是:我该如何调试这个东西? Where's the details about which foreign key in which object has which value but shouldn't have it?关于哪个对象中的哪个外键具有哪个值但不应该具有它的详细信息在哪里? Are there trace logs available for Entity Framework that contain internal data about what was done?是否有可用于 Entity Framework 的跟踪日志,其中包含有关已完成操作的内部数据?

The situation is way too complex to show it here so please don't ask for it.情况太复杂了,无法在这里展示,所以请不要要求它。 I want to help myself out of this, I just need assistence with that.我想帮助自己摆脱这个,我只是需要帮助。

You can override SaveChanges method of DBContext, and see what all properties are update/deleted/modified, it will minimize the list you need to check for your error.您可以覆盖 DBContext 的 SaveChanges 方法,并查看所有属性的更新/删除/修改,它将最小化您需要检查错误的列表。 I needed just deleted/detached ones, but you can modify .where for what you need.我只需要删除/分离的那些,但您可以根据需要修改.where

public override int SaveChanges()
        {
            try
            {
                var debug = false;

                if (debug)
                {
                    var modifiedEntities = ChangeTracker.Entries()
                            .Where(p => p.State == EntityState.Deleted || p.State == EntityState.Detached).ToList();

                    foreach (var change in modifiedEntities)
                    {
                        var entityName = change.Entity.GetType().Name;
                        System.Diagnostics.Debug.WriteLine(string.Format("Entity {0}", entityName));

                    }
                }


                return base.SaveChanges();
            }
            catch (DbEntityValidationException e)
            {
                foreach (var eve in e.EntityValidationErrors)
                {
                    Debug.WriteLine("Error while Save Changes:");
                    Debug.WriteLine("Entity {0} has the following validation errors:", eve.Entry.Entity.GetType().Name);
                    foreach (var ve in eve.ValidationErrors)
                    {
                        Debug.WriteLine("Property:{0}, Error: {1}",
                            ve.PropertyName, ve.ErrorMessage);
                    }
                }
                throw;
            }
            catch (Exception)
            {
                throw;
            }
        }

You can log SQL您可以记录 SQL

using (var context = new BlogContext())
{
    context.Database.Log = Console.Write;

    // Your code here...
}

Even more you can make a custom log formatter like this您甚至可以像这样制作自定义日志格式化程序

public class OneLineFormatter : DatabaseLogFormatter
{
    public OneLineFormatter(DbContext context, Action<string> writeAction)
        : base(context, writeAction)
    {
    }

    public override void LogCommand<TResult>(
        DbCommand command, DbCommandInterceptionContext<TResult> interceptionContext)
    {
        Write(string.Format(
            "Context '{0}' is executing command '{1}'{2}",
            Context.GetType().Name,
            command.CommandText.Replace(Environment.NewLine, ""),
            Environment.NewLine));
    }

    public override void LogResult<TResult>(
        DbCommand command, DbCommandInterceptionContext<TResult> interceptionContext)
    {
    }
}

You can intercept the exact exception by your own log formatter for that exact exception assuming it is 'DbEntityValidationException'假设它是“DbEntityValidationException”,您可以通过自己的日志格式化程序拦截该确切异常的确切异常

public class MyExcpetionCommandInterceptor : IDbCommandInterceptor
{


    public void NonQueryExecuting(
        DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
    {
        LogIfNonAsync(command, interceptionContext);
    }

    public void NonQueryExecuted(
        DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
    {
        LogIfError(command, interceptionContext);
    }

    public void ReaderExecuting(
        DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
    {
        LogIfNonAsync(command, interceptionContext);
    }

    public void ReaderExecuted(
        DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
    {
        LogIfError(command, interceptionContext);
    }

    public void ScalarExecuting(
        DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
    {
        LogIfNonAsync(command, interceptionContext);
    }

    public void ScalarExecuted(
        DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
    {
        LogIfError(command, interceptionContext);
    }

    private void LogIfNonAsync<TResult>(
        DbCommand command, DbCommandInterceptionContext<TResult> interceptionContext)
    {
        if (!interceptionContext.IsAsync)
        {
            Logger.Warn("Non-async command used: {0}", command.CommandText);
        }
    }

    private void LogIfError<TResult>(
        DbCommand command, DbCommandInterceptionContext<TResult> interceptionContext)
    {
        if (interceptionContext.Exception.GetType() == typeof(DbEntityValidationException) || typeof(DbEntityValidationException).IsAssignableFrom(interceptionContext.Exception.GetType()) )
        {
            Logger.Error("Command {0} failed with exception {1}",
                command.CommandText, interceptionContext.Exception);
        }
    }
}

There is a nice article about that in Microsoft Logging and intercepting database operations在 Microsoft Logging 和拦截数据库操作中有一篇很好的文章

暂无
暂无

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

相关问题 操作失败:由于一个或多个外键属性不可为空,因此无法更改该关系。 - The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable. 由于一个或多个外键属性不可为空,因此无法更改关系。 关系发生变化时 - he 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 relationship could not be changed because one or more of the foreign-key properties is non-nullable. When Inserting a new Entity EF 6.1.1-无法更改关系,因为一个或多个外键属性不可为空 - EF 6.1.1 - The relationship could not be changed because one or more of the foreign-key properties is non-nullable 实体框架无法更改关系,因为一个或多个外键属性不可为空 - Entity Framework The relationship could not be changed because one or more of the foreign-key properties is non-nullable EF 6:插入多个-无法更改关系,因为一个或多个外键属性不可为空 - EF 6: inserting multiple - The relationship could not be changed because one or more of the foreign-key properties is non-nullable 操作失败:无法更改关系,因为一个或多个外键属性不可为空 - The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable 由于一个或多个外键属性不可为空,因此无法更改该关系 - The relationship could not be changed because one or more of the foreign-key properties is non-nullable EF添加实体:由于一个或多个外键属性不可为空,因此无法更改关系 - EF adding entity: The relationship could not be changed because one or more of the foreign-key properties is non-nullable 实体框架5无法更改该关系,因为一个或多个外键属性不可为空 - Entity Framework 5 The relationship could not be changed because one or more of the foreign-key properties is non-nullable
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM