插入具有一对多关系但不在两个表中创建记录的新实体

本文关键字:两个 创建 记录 实体 新实体 一对多 关系 插入 | 更新日期: 2023-09-27 18:24:56

我正在使用MVC5和EF6 Code First创建一个新的Company实体,该实体可以有许多Contact实体。但是,只有Company记录被写入数据库。

型号:

public class Company
{
    public virtual int CompanyId { get; set; }
    [Required]
    public virtual string Name { get; set; }
    [Required]
    public virtual Address Address { get; set; }
    [Required]
    public virtual string Phone { get; set; }
    public virtual string Email { get; set; }
    // can have many Contacts
    public virtual IEnumerable<Contact> Contacts { get; set; }
}
public class Contact
{
    public virtual int ContactId { get; set; }
    [Required]
    public virtual string Title { get; set; }
    [Required]
    public virtual string Forename { get; set; }
    [Required]
    public virtual string Surname { get; set; }
    [Required]
    public virtual string Phone { get; set; }
    public virtual string Email { get; set; }
    // belongs to one Company
    public virtual Company Company { get; set; }
}

控制器:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> Create_POST([Bind(Include = "CallerType,Name,Address,Phone,Email,Contacts")] CompanyViewModel viewModel)
    {
        if (ModelState.IsValid)
        {
            // tried commented code to make sure it wasn't a problem with my repository and contact records aren't saved to database...
            //var context = new EfDbContext();
            //var company = new Company
            //{
            //    Name = viewModel.Name,
            //    Phone = viewModel.Phone,
            //    Address = viewModel.Address,
            //    Email = viewModel.Email
            //};
            //context.Companies.Add(company);
            //var contact = new Contact
            //{
            //    Company = company,
            //    Title = "mr",
            //    Forename= "f",
            //    Surname = "s",
            //    Phone = "132"
            //};
            //var contact2 = new Contact
            //{
            //    Company = company,
            //    Title = "mr",
            //    Forename = "for",
            //    Surname = "sur",
            //    Phone = "987"
            //};
            //var contacts = new List<Contact> {contact, contact2};
            //company.Contacts = contacts;
            //context.SaveChanges();

            var contacts = viewModel.Contacts.Select(c => new Contact
            {
                Title = c.Title,
                Forename = c.Forename,
                Surname = c.Surname,
                Phone = c.Phone,
                Email = c.Email
            });
            var company = new Company
            {
                Name = viewModel.Name,
                Phone = viewModel.Phone,
                Address = viewModel.Address,
                Email = viewModel.Email,
                Contacts = contacts
            };
            await _companyRepository.CreateAsync(company);
            var redirectUrl = new UrlHelper(Request.RequestContext).Action("Create", "Enquiry", new { id = company.CompanyId, callerType = viewModel.CallerType });
            return Json(new { Url = redirectUrl });
        }
        Response.StatusCode = 400;
        return PartialView("~/Views/Company/_Create.cshtml", viewModel);
    }

存储库:

    public async Task<TEntity> CreateAsync(TEntity entity)
    {
        if (entity == null) throw new ArgumentNullException(nameof(entity));
        DbContext.Set<TEntity>().Add(entity);
        await DbContext.SaveChangesAsync();
        return entity;
    }

我的印象是,DbContext会"知道",因为它的Contacts集合已填充,它会创建链接到创建的CompanyContact记录。还是我必须创建一个Contact,因为这是一个包含外键的表,EF会"知道"首先创建Company

还是需要先使用SaveChanges()保存Company实体,然后将其分配给Contact记录并执行第二个SaveChanges()
如果是这种情况,那么我需要使用Database.BeginTransaction()吗?

任何关于这方面的指导都将是伟大的,因为这是我第一次使用实体框架。

插入具有一对多关系但不在两个表中创建记录的新实体

Contacts必须是ICollection。EF不支持IEnumerable作为导航属性,因为无法向其中添加项目。

这也意味着您应该更改创建contacts:的代码

var contacts = viewModel.Contacts.Select(c => new Contact
{
    Title = c.Title,
    Forename = c.Forename,
    Surname = c.Surname,
    Phone = c.Phone,
    Email = c.Email
}).ToList();  // <= ToList() added

您的关系应该在DbContext中通过重写OnModelCreating方法来设置

我自己是实体框架的新手,但发现方法名称有助于学习如何建立关系

希望以下内容能帮助

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Company>()
                    .HasMany(c => c.Contacts)
                    .WithRequired(co => co.Company)
                    .HasForeignKey(co => co.CompanyId);
}

您还可以在关系中设置级联,这样当一个实体被删除时,相关的实体也会被删除,如果您需要删除公司,这可能是需要考虑的问题