【问题标题】:Fluent NHibernate mapping - converting n-m to 1-n relation流畅的 NHibernate 映射 - 将 n-m 转换为 1-n 关系
【发布时间】:2014-08-16 22:18:29
【问题描述】:

我创建了三个实体:

public class Company : EntityBase
{
   some properties
   public virtual IList<UserCompanyAttachment> AttachedUsers {get; set;}

   public virtual void AttachUser(User userToAttach)
   {
       var userCompanyAttachment = new UserCompanyAttachment()
       {
           AttachedCompany = this,
           AttachedUser = userToAttach
       }
       AttachedUsers.Add(userCompanyAttachment);
   }
}

public class User : EntityBase
{
   some properties
   public virtual IList<UserCompanyAttachment> AttachedCompanies {get; set;}

   public virtual void AttachCompany(Company companyToAttach)
   {
       var userCompanyAttachment = new UserCompanyAttachment()
       {
           AttachedCompany = companyToAttach,
           AttachedUser = this
       }
       AttachedCompanies.Add(userCompanyAttachment);
   }
}

public class UserCompanyAttachment : EntityBase
{
    public virtual User AttachedUser { get; set; }
    public virtual Company AttachedCompany { get; set; }
     .. some properties ..
}

我已经用 fluent 创建了关系 - 公司和用户映射得到:

HasMany(x => x.AttachedCompanies/Users).Inverse.Cascade.All();

UserCompanyAttachemnt 映射为:

References(x => x.AttachedUser);
References(x => x.AttachedCompany);

我之所以没有创建正常的多对多关系是因为我需要存储有关附件的信息。 (没有冗余,因为在这两种情况下,数据库中都存在物理上的第三个表)但是,当我尝试使用 companyObject.AttachUser(newUser) 附加用户时,更改仅在 company.AttachedUsers 上可见 - 但在 newUser.AttachedCompanies 中不可见。有没有办法通过一些映射来推动更改?为什么会失败?

编辑:添加了失败的单元测试

    [Test]
    public void CanCorrectlyMapUserCompanyAttachmentWhenAddedByUser()
    {
        var testUser = new User() { PasswordHash = "pp", PasswordSalt = "qq", Username = "user" };
        var testCompany = new Company()
        {
            Address = new Address() { City = "q" },
            AgentName = "tt",
            Comments = "z",
            CompanyName = "g",
            MailAddress = "@@",
            NIP = 231123
        };

        DbSession.Save(testUser);
        DbSession.Save(testCompany);
        testUser.AttachCompany(testCompany);
        DbSession.Flush();

        var addedAttachment = DbSession.Get<UserCompanyAttachment>(1);

        User addedUser = DbSession.Get<User>(1);
        Company addedCompany = DbSession.Get<Company>(1);

        Assert.AreEqual(addedAttachment .AttachedUser.Id, 1);
        Assert.AreEqual(addedAttachment .AttachedCompany.Id, 1);
        Assert.IsTrue(addedUser.AttachedCompanies.Contains(addedAttachment));
        Assert.IsTrue(addedCompany.AttachedUsers.Contains(addedAttachment)); // here it fails
    }

【问题讨论】:

    标签: c# nhibernate fluent-nhibernate


    【解决方案1】:

    这里的问题是:

    • 我们在C#将配对实例UserCompanyAttachment分配到AttachedUsers集合Company实例testCompany
    • 我们确实没有让 NHibernate 从 DB 重新加载所有三个 - 刚刚创建的实例。仍然从会话返回的所有对象 - 它的一级缓存。

    那么,我们能做的是:

    1) 还将配对对象分配到公司的集合AttachedUsers。但我不会把事情复杂化这么多。因为我们的操作应该始终是读或写。他们每个人都应该有自己的分离/独特的ISession。 (即不共享一级缓存)

    2) 首选方法是将其保留在 NHibernate 上。这个很棒的工具将填充我们所期望的所有集合。它只需要被允许重新加载数据库中的所有东西。如何?只需一行代码:

    // creation of all the stuff in the unit test 
    ...
    ...
    DbSession.Flush();
    
    // new line - essential setting - clearing the first level cache
    DbSession.Clear();
    
    // the test continues as it was... passing all assertion
    ...
    

    这句话很简单:DbSession.Clear(); 是成功的关键。为什么?因为 NHibernate 现在可以完全访问基于数据库数据的正确实例化......而不是我们 C# 中的“弱集关系”。

    这将是首选方式:拆分写入和读取 == 让 NHibernate 填充我们的对象,它会正确完成...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-08-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-14
      相关资源
      最近更新 更多