简体   繁体   English

如何在Entity Framework中获取新条目的主键并设置FK关系

[英]How to get primary key in Entity Framework for a new entry and set FK Relationship

In my ASP.NET MVC 5 application, I have situation where I need to get the primary key that got generated for a particular entry in database. 在我的ASP.NET MVC 5应用程序中,我遇到需要获取为数据库中特定条目生成的主键的情况。 Also, I need to get that id and set a foreign key relationship in database. 另外,我需要获取该ID并在数据库中设置外键关系。 I have tried below attempt and it seems to be working but I had to call _context.SaveChanges() TWICE. 我在下面的尝试中尝试过,它似乎正在工作,但是我不得不_context.SaveChanges()调用_context.SaveChanges()

UI Behaviour: the user has a dropdown with a list of companies in referral form. 用户界面行为:用户具有一个下拉列表,其中包含推荐形式的公司列表。 When a company is not found, user will select "Others" in the dropdown. 当找不到公司时,用户将在下拉菜单中选择“其他”。 And it will show a textbox, where user will enter the company name. 它将显示一个文本框,用户可以在其中输入公司名称。 So I need to add this company to the database and link it to the referral row. 因此,我需要将该公司添加到数据库中并将其链接到引荐行。

Relationship between tables Referral and Company : ReferralCompany之间的关系:

 dBModelBuilder.Entity<Company>()
            .HasMany(u => u.Referrals)
            .WithRequired(u => u.Company)
            .HasForeignKey(u => u.CompanyId);

Model classes: 模型类别:

public class Company
{
    [Key]
    public int CompanyId { get; set; }
    public string CompanyName { get; set; }

    public ICollection<Referral> Referrals { get; set; }
    public ICollection<CoverLetter> CoverLetters { get; set; }
}

public class Referral
{
    [Key]
    public int ReferralId { get; set; }

    [Display(Name = "REFERRALS")]
    public string ReferralName { get; set; }

    public int? CoverLetterId { get; set; }
    public virtual CoverLetter CoverLetter { get; set; }

    public int CompanyId { get; set; }
    public virtual Company Company { get; set; }
}

ViewModel: ViewModel:

public class Referral
{
    [Key]
    public int ReferralId { get; set; }

    [Display(Name = "REFERRALS")]
    public string ReferralName { get; set; }

    public int? CoverLetterId { get; set; }
    public virtual CoverLetter CoverLetter { get; set; }

    public int CompanyId { get; set; }
    public virtual Company Company { get; set; }
}

My attempt inside the controller action: 我在控制器动作中的尝试:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create(ReferralViewModel viewModel)
    {
        var candidateId = User.Identity.GetUserId();

        var referral = new Referral
        {
            ReferralName = viewModel.ReferralName,
        };

        if (viewModel.CompanyId.HasValue)
        // if it is option 4 then we need to add it to the company table
        {
            if (!string.IsNullOrEmpty(viewModel.TempCompany))
            {
                var f = new Company
                {
                    CompanyName = viewModel.TempCompany
                };

                _context.Companies.Add(f);
               // ********FIRST CALL
                 _context.SaveChanges(); 

                _context.Referrals.Add(referral);
                 referral.CompanyId = f.CompanyId;
               // **********SECOND CALL
                _context.SaveChanges(); // SECOND CALL ------
            }
            else
            {
                referral.CompanyId = viewModel.CompanyId.Value;
                _context.Referrals.Add(referral);
                _context.SaveChanges();
            }
        }

        return RedirectToAction("ReferralCenter");
    }

Question: can I do these steps in one call to _context.SaveChanges(); 问题:我可以一次调用_context.SaveChanges();来执行这些步骤_context.SaveChanges(); ?

EDIT 编辑

With this code, I get a NullReferenceException : 有了这段代码,我得到了NullReferenceException

if (!string.IsNullOrEmpty(viewModel.TempCompany))
{
    var f = new Company
                {
                    CompanyName = viewModel.TempCompany
                };

    f.Referrals.Add(referral); // Referrals is NULL(EXCEPTION)
    _context.Companies.Add(f);
    // _context.SaveChanges();
    //_context.Referrals.Add(referral);
    // referral.CompanyId = f.CompanyId;
    _context.SaveChanges();
}

If you have the navigation property defined, you could just save both the Company and Referral in one shot as follows: 如果定义了导航属性,则可以将“公司”和“推荐人”保存在一张照片中,如下所示:

if (!string.IsNullOrEmpty(viewModel.TempCompany))
{
   var f = new Company
   {
        CompanyName = viewModel.TempCompany
   };
   referral.Company = f;
   _context.SaveChanges();
}

EF will take care of setting the FK. EF将负责设置FK。

EDIT 编辑

Have updated the code to include _context.Referrals.Add(referral) as mentioned in the comments: 如注释中所述,已更新代码以包含_context.Referrals.Add(referral)

if (!string.IsNullOrEmpty(viewModel.TempCompany))
{
   var f = new Company
   {
        CompanyName = viewModel.TempCompany
   };

   referral.Company = f;
   _context.Referrals.Add(referral);
   _context.SaveChanges();
}

It is my understanding that FK constraints are managed within EF, so long as they are configured in the DB. 据我了解,只要在数据库中配置FK约束,就可以在EF中对其进行管理。

If in your EF model the Referral is a child of Company then there should be a referrals collection accessible from the Company object instance. 如果在您的EF模型中,引荐是Company的子级,则应该有一个可以从Company对象实例访问的引荐集合。

UPDATE I just built a simple sample MVC Proj, 2x SQL tables (Referrals and Company FK on CompanyId) 4 x Companies, 4th being OTHER, built an EF model with Reverse POCO for speed, added a Controller with scaffolding and views and modified my controller to the below. 更新我刚刚建立了一个简单的示例MVC Proj,2个SQL表(在CompanyId上引用和公司FK)4个公司,第4个是OTHER,使用反向POCO建立了EF模型以提高速度,添加了具有脚手架和视图的Controller并修改了我的控制器到下面。 (I just insert the date time rather than tempCompanyName. The syntax generated here is more like that in the answer by @ashin, but it works for me. (我只是插入日期时间而不是tempCompanyName。此处生成的语法更像@ashin的答案中的语法,但它对我有用。

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create([Bind(Include = "ReferralId,CompanyId")] Referral referral)
    {
        if (ModelState.IsValid)
        {
            if (referral.CompanyId == 4)
            {
                var f = new Company() { Name = DateTime.Now.ToString() };
                referral.Company = f;
            }
            db.Referrals.Add(referral);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        ViewBag.CompanyId = new SelectList(db.Companies, "CompanyId", "Name", referral.CompanyId);
        return View(referral);
    }

My Company model does instanciate a new Referrals Collection 我的公司模型确实建立了新的推荐人集合

    public Company()
    {
        Referrals = new System.Collections.Generic.List<Referral>();
    } 

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

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