运维开发网

在C#中实体框架迁移 – 参照完整性约束违规

运维开发网 https://www.qedev.com 2020-04-08 12:22 出处:网络 作者:运维开发网整理
我一直在努力解决这个问题,并且无法在Stack Overflow上找到解决方案. 我有一个MVC应用程序,它使用Entity Framework with Repository和Unit of Work模式.我最近从使用网络数据库(Sql Server 2008 R2,问题似乎不存在)转移到本地数据库并开始使用Entity Framework迁移,以便与其他开发人员合作,而不是通过对其进行更改来相
我一直在努力解决这个问题,并且无法在Stack Overflow上找到解决方案.

我有一个MVC应用程序,它使用Entity Framework with Repository和Unit of Work模式.我最近从使用网络数据库(Sql Server 2008 R2,问题似乎不存在)转移到本地数据库并开始使用Entity Framework迁移,以便与其他开发人员合作,而不是通过对其进行更改来相互影响我们的模特.

我的模型看起来像这样:

[Table("Student")]
public class Student
{
    [Key]
    public int Id { get; set; }

    <... other fields ...>

    [Required(ErrorMessage = "A student type is required")]
    public int StudentTypeId { get; set; }

    [Required(ErrorMessage = "A student status is required")]
    public int StudentStatusId { get; set; }

    [ForeignKey("StudentTypeId")]
    public Virtual StudentType StudentType { get; set; }

    [ForeignKey("StudentStatusId")]
    public Virtual StudentStatus StudentStatus { get; set; }
}

每次我尝试更新Student的StudentStatus属性时,我都会遇到以下异常:

“已成功提交对数据库的更改,但更新对象上下文时发生错误.

ObjectContext可能处于不一致状态.内部异常消息:发生参照完整性约束违规:

关系一端的’StudentStatus.Id’的属性值与另一端’Student.StudentStatusId’的属性值不匹配.“

我已经尝试在保存更改之前将导航属性重新设置为null.

student.StudentStatus = null;
student.StudentStatusId = 26;
_studentRepository.Update(student);
_unitOfWork.Commit();

我已经尝试检索特定的StudentStatus对象:

var studentStatus = _studentStatusRepository.GetById(26);
student.StudentStatusId = 26;
student.StudentStatus = studentStatus;
_studentRepository.Update(student);
_unitOfWork.Commit();

但每次尝试它都会在DataContext.SaveChanges()上抛出相同的异常.

我可以毫无问题地更新StudentType(字面意思是同一种关系和类似的类).

Update方法的实现:

public Virtual void Update(T entity)
{
    try
    {
        DataContext.Entry(entity).State = EntityState.Modified;
    }
    catch (Exception exception)
    {
        throw new EntityException(string.Format("Failed to update entity '{0}'", typeof(T).Name), exception);
    }
}

我注意到,与我以前的网络数据库相比,EF Migrations在数据库中创建了更多的索引,但我已经手动删除它们(不是我认为它们一定是问题).我尝试比较两个数据库中的关系,一切似乎都是一样的.

我知道如果没有我提供更多信息可能很难指出可能出现什么问题,但是还有什么可能导致这个问题呢?

编辑(添加了StudentStatus类和相应的StudentStatusType)

[Table("StudentStatus")]
public class StudentStatus
{
    [Key]
    public int Id { get; set; }

    [Required(ErrorMessage = "Student status name is required")]
    [MaxLength(50, ErrorMessage = "Student status name cannot be longer than 50 characters")]
    public string Name { get; set; }

    public int StudentStatusTypeId { get; set; }

    [ForeignKey("StudentStatusTypeId")]
    public Virtual StudentStatusType StudentStatusType { get; set; }
}

[Table("StudentStatusType")]
public class StudentStatusType
{
    [Key]
    public int Id { get; set; }
    public string Name { get; set; }
}

编辑2

我忘了提到我在存储库级别启用了数据库日志记录,以查看Entity Framework正在执行哪些SQL查询:

DataContext.Database.Log = s => Debug.WriteLine(s);

结果是:

UPDATE [dbo].[Student]
SET <... some parameters ...>, [StudentStatusId] = @10, <... some parameters ...>
WHERE ([Id] = @14)

UPDATE [dbo].[Student]
SET <... some parameters ...>, [StudentStatusId] = @10, <... some parameters ...>
WHERE ([Id] = @14)

<... some parameters ...>

-- @10: '25' (Type = Int32)

-- @10: '25' (Type = Int32)

<... some parameters ...>

-- Executing at 12/01/2015 12:30:41 +00:00

-- Executing at 12/01/2015 12:30:41 +00:00

-- Completed in 0 ms with result: 1

-- Completed in 0 ms with result: 1

那么为什么EF试图插入25的值,即使我明确指定为26?这会导致潜在的问题吗?另外,为什么会有两个更新语句而不是一个?

对我来说,这种方法似乎更直观:

int StudentStatusType保存StudentStatusType.Id的值,因此应将其标记为[ForeignKey].

如果添加虚拟StudentStatusType属性,EntityFramework将自动绑定它.

[Table("StudentStatus")]
public class StudentStatus
{
    [Key]
    public int Id { get; set; }

    [Required(ErrorMessage = "Student status name is required")]
    [MaxLength(50, ErrorMessage = "Student status name cannot be longer than 50 characters")]
    public string Name { get; set; }

    [ForeignKey("StudentStatusType")] 
    public int StudentStatusTypeId { get; set; }
    public Virtual StudentStatusType StudentStatusType { get; set; }
}

[Table("StudentStatusType")]
public class StudentStatusType
{
    [Key]
    public int Id { get; set; }
    public string Name { get; set; }
}
0

精彩评论

暂无评论...
验证码 换一张
取 消