繁体   English   中英

实体框架-Botched关联

[英]Entity Framework - Botched association

我正在尝试使用Entity Framework 6.1.3创建“首先从数据库编写代码”类,但是EF似乎在建立关联时遇到麻烦(或者我只是在数据库中未正确设置某些内容)。

这是有问题的两个表,我正在使用实体框架来制作类;

数据库架构

在我的数据库中,CVE与AssessmentChecks有一对多关系。 因此,EvaluationChecks表本身具有外键;

ALTER TABLE NVD.[AssessmentChecks] ADD CONSTRAINT
    FK_AssessmentChecks_CVE FOREIGN KEY
    (
    CveIDFK
    ) REFERENCES NVD.CVE
    (
    CveID
    ) ON UPDATE  NO ACTION 
     ON DELETE  NO ACTION 

但是,当我从该数据库创建类时,Entity Framework会将“ CveIDFK”标记为必填字段...

public partial class AssessmentCheck
{
    public int AssessmentCheckID { get; set; }

    [Required]
    [StringLength(20)]
    public string CveIDFK { get; set; }

    public string AssessmentCheckSystem { get; set; }

    public string AssessmentCheckURL { get; set; }

    [StringLength(200)]
    public string AssessmentCheckName { get; set; }

    public virtual CVE CVE { get; set; }
}

如果我使用同一数据库来创建EDMX文件(EF设计器,而不是“代码优先”),则模型图和评估检查类如下所示(这是我所期望的);

CVE评估检查NVD数据库

public partial class AssessmentCheck
{
    public int AssessmentCheckID { get; set; }
    public string CveID { get; set; }
    public string AssessmentCheckSystem { get; set; }
    public string AssessmentCheckURL { get; set; }
    public string AssessmentCheckName { get; set; }

    public virtual CVE CVE { get; set; }
}

是什么赋予了? 如何使Entity Framework在代码优先模型中创建关联,以使“ CveIDFK”不是“ Required”?

明确地说,我的最终目标是从数据库创建类,创建“ CVE”对象,向“ CVE”对象添加“ AssessmentCheck”,然后“ SaveChanges”。 问题是当我这样做并尝试保存更改时,EF表示我需要显式提供“ AssessmentCheck”对象的“ CveIDFK”字段。 我相信,鉴于CVE与AssessmentChecks之间的关系,应该自动暗示该FK。 我想念什么吗?


编辑:

我更新了数据库,以返回使用CveID“作为AssessmentChecks表中外键的名称,并重新创建了我的类。

这是我用来尝试保存数据的代码;

CVE cve = new CVE
            {
                CveID = "CVE-2016-2140"
            };

            AssessmentCheck AC1 = new AssessmentCheck
            {
                AssessmentCheckName = "First Assessment check"
            };

            AssessmentCheck AC2 = new AssessmentCheck
            {
                AssessmentCheckName = "Second Assessment Check"
            };

            cve.AssessmentChecks.Add(AC1);
            cve.AssessmentChecks.Add(AC2);

            using (var context = new NVDModel())
            {
                try
                {
                    context.Database.Log = Console.WriteLine;
                    context.CVEs.Add(cve);       
                    context.SaveChanges();
                }
            }

我得到的错误是

状态为“已添加”的类型为“ AssessmentCheck”的实体具有以下验证错误:-属性:“ CveID”,错误:“需要CveID字段。” 状态为“已添加”的类型为“ AssessmentCheck”的实体具有以下验证错误:-属性:“ CveID”,错误:“需要CveID字段。”

如果我从“ AssessmentChecks”类的“ CveID”字段中删除“必需”数据注释,则它可以工作(在没有显式提供的情况下自动插入外键),但是我认为我不必删除此数据注释。

另外,如果我在将父项添加到上下文中之后移动了子项的添加,那也可以;

try
                {
                    context.Database.Log = Console.WriteLine;
                    context.CVEs.Add(cve);
                    cve.AssessmentChecks.Add(AC1);
                    cve.AssessmentChecks.Add(AC2);
                    context.SaveChanges();
                }

这里发生了什么?

将实体添加到dbset(在您的情况下为CVE)实体框架后,便开始跟踪对其所做的任何更改,因此,当您将子对象(AssessmentCheck)添加到该实体中时,便可以通过您提供的信息来分配父ID,即在代码优先的情况下进行数据注释。 因此,第二种第二种方法正在工作。

在第一种方法中,如果您使用身份(即自动生成)而不是为CVE提供PK(CveId),那么您将能够实现相同的目的,但是由于无法将字符串用作CVE身份中的PK,因此一个简单的解决方案是将int作为PK并将现有的CveId设置为唯一键,否则使用自定义添加而不是cve.AssessmentChecks.Add ...将FK分配/设置为子代。

如果在保存更改之前使用以下方法,则可以看到此操作

var entitychanges = context.ChangeTracker.Entries().Where(e => e.State == EntityState.Added);

您会注意到在第一种方法中未为AssessmentCheck设置CveID,而在第二种方法中则未设置。

暂无
暂无

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

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