EF是否跟踪相关模型,并在需要时设置其外键?

时间:2016-12-04 18:06:07

标签: c# asp.net-mvc-5 entity-framework-6

我有两个与他们有关系的EF模型/类:会员 MembershipSeason 。一个会员可以有多个 MembershipSeasons 。一个 MembershipSeason 模型在db中具有外键引用( MemberID )到成员模型。

Member.cs

public class Member
{
        public int MemberID { get; set; }

        //some properties left out
        public virtual ICollection<MembershipSeason> MembershipSeasons { get; set; }
 }

MembershipSeason.cs

public class MembershipSeason
{
        [Key]
        public int MembershipSeasonID { get; set; }

        //some properties left out
        public int MemberID { get; set; }
        public virtual Member Member { get; set; }
}

我尝试将这两个模型同时发布到同一个创建方法。我发现EF跟踪这两个模型并将它们作为新模型保存到db中。它还通过将新成员模型的 MemberID 设置为db中新的 MembershipSeason 模型的外键来链接这两个模型。我想这是计划行为? - 我的意思是EF将相关模型的外键设置为自动似乎是预期的行为 - 事情应该如何运作。因此,我想我不需要首先保存会员模型,获取 MemberID 并将其用于 MembershipSeason 并将其单独保存在< strong>创建方法? (因为EF为你工作)

 db.Members.Add(member);

 db.MembershipSeasons.Add(membershipSeason);

 await db.SaveChangesAsync(); 

上面和下面的创建方法的工作方式是不需要将 MemberID 属性直接设置为 MembershipSeason 模型,因为EF自动完成。

MemberController.cs

public class MemberController : Controller
{
        private MembersContext db = new MembersContext();

        //some code left out

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Create([Bind(Include = "MemberNumber,FirstName,LastName")] Member member,
            [Bind(Include = "HasPaidMembership,SeasonId")] MembershipSeason membershipSeason)
        {
            try
            {
                if (ModelState.IsValid)
                {
                    db.Members.Add(member);

                    db.MembershipSeasons.Add(membershipSeason);

                    await db.SaveChangesAsync();

                    return RedirectToAction("Index");
                }
            }
            catch (DataException /* dex */)
            {
            }
            return View(member);
        }
    }

我是EF和ASP.NET MVC的新手,所以我试图解决这些问题。任何帮助表示赞赏 - 谢谢。

1 个答案:

答案 0 :(得分:2)

  

它还通过将新成员模型的MemberID设置为db中新的MembershipSeason模型的外键来链接这两个模型。我想这是计划行为?

TL; DR:

是的,它必须是必需的行为。让我们从读取开始:

public class Organization
{
  public Guid Id { get; set; }
}

public class Employee
{
  public Guid Id { get; set; }
  public Guid OrganizationId { get; set; }
  public Organization Organization { get; set; }
}

public Employee GetEmployeeWithOrganization(guid id)
{
  var result = _context.Employees
    .Include(e => e.Organization)
    .FirstOrDefault(e => e.Id = id);
}

基本上当你要求EF包含导航属性时,你会得到一个像对象图:

Employee
- Id : <guid1>
- OrganizationId : <guid2>
- Organization : object
  - Id : <guid2>

假设因为EF should keep track of entities因为如果你这样做会发生什么是常识:

var employee = GetEmployeeWithOrganization(<guid1>)

var org = new Organization { id = guid.NewGuid() }; //<guid3>

employee.Organization = org;

_context.SaveChanges();

其中一个是有效对象:

A:

Employee
- Id : <guid1>
- OrganizationId : <guid2>  // <-- difference
- Organization : object
  - Id : <guid3>

B:

Employee
- Id : <guid1>
- OrganizationId : <guid3>  // <-- difference
- Organization : object
  - Id : <guid3>

A无效,因为你不能依赖这些值,对这个对象进行编程不仅是一场彻头彻尾的噩梦,而且在数据库层面没有意义。 B有效,它是您可以信赖的数据。

这也意味着您可以预先缓解项目,EF会自动编写它们。考虑:

var org = GetOrganization(<guid3>);

var emp = GetEmployee(<guid1>);

Assert.That(emp.Organization, Is.Not.Null);  // passes

这是因为EF正在跟踪组织,并且因为EF已将org配置为员工的FK。