【问题标题】:Collection is not selected with NHibernate-Caching未使用 NHibernate-Caching 选择集合
【发布时间】:2012-09-06 20:29:39
【问题描述】:

我有闲散的实体:

人 公司

然后,有一个实体 PersonCompany,它在 Person 和 Company 之间建立关系

Person 的映射是:

public class PersonMap : SubclassMap<Person> {
    public PersonMap() {
        this.Table("Person");
        this.KeyColumn("Id");
        this.HasMany(x => x.PersonCompanys).AsSet().KeyColumn("PersonId").Fetch.Select().Inverse().Cascade.Delete();
    }
}

公司:

public class CompanyMap : SubclassMap<Company> {
    public CompanyMap() {
        this.Table("Company");
        this.KeyColumn("Id");
        this.HasMany(x => x.PersonCompanys).AsSet().KeyColumn("CompanyId").Fetch.Select().Inverse().Cascade.None();
    }
}

和个人公司:

public class PersonCompanyMap : ClassMap<PersonCompany> {
    public PersonCompanyMap() {
        this.Table("PersonCompany");

        this.Version(x => x.ObjectVersion);
        this.Id(x => x.Id).GeneratedBy.Assigned();
        this.References(x => x.Company).Column("CompanyId").Fetch.Select();
        this.References(x => x.Person).Column("PersonId").Fetch.Select();
    }
}

SecondLevel-Caching 被激活一般并且对于每个具有约定的实体。还有 PersonCompanys-Collection 的缓存:

public class CachableConventions : IClassConvention, IHasManyConvention, IHasManyToManyConvention {
    private static readonly Type[] notCachableTypes = new[] {typeof(Word), typeof(ActivityWord), typeof(DbVersion), typeof(Deleted), typeof(ExchangeSyncState), typeof(Synchronizer), typeof(SerialletterField)};

    public void Apply(IClassInstance instance) {
        if (Array.IndexOf(notCachableTypes, instance.EntityType) >= 0) {
            return;
        }
        instance.Cache.ReadWrite();
    }

    public void Apply(IManyToManyCollectionInstance instance) {
        if (Array.IndexOf(notCachableTypes, instance.ChildType) >= 0) {
            return;
        }
        instance.Cache.ReadWrite();
    }
    public void Apply(IOneToManyCollectionInstance instance) {
        if (Array.IndexOf(notCachableTypes, instance.ChildType) >= 0) {
            return;
        }
        instance.Cache.ReadWrite();
    }
}

现在,我创建了一个新的 Person 并保存了一个新的 Company,然后我将 PersonCompany-Record 添加到 PersonCompanies-Collection。

当我选择创建的 Person 后,PersonCompanys-Collection 将为空。 当我在没有 SecondLevel-Caching 的情况下执行相同操作时,PersonCompanys-Collection 包含创建的实体。

有人知道,这里出了什么问题吗?

编辑 - 附加信息:

这是导致问题的步骤:

  1. 使用Session.Save(person) 创建一个新人
  2. person = Session.Get(person.Id)加载人
  3. 从具有personCompany = person.PersonCompany.FirstOrDefault() 的人那里获取personCompany(这将为空)
  4. 使用Session.Save(new PersonCompany(Guid.NewGuid()) {Person = person})) 创建一个新的 PersonCompany-Entry
  5. person = Session.Get(person.Id)加载人
  6. 现在,person.PersonCompany 返回一个空列表。

当我不执行第 3 步时,一切正常。

【问题讨论】:

  • 我的直觉是这与您的缓存几乎没有关系。在创建 Person、Company 和 PersonCompany 对象期间,如果没有看到您在做什么,我无能为力。
  • 当我停用二级缓存时,它工作正常。也许问题是我如何将 Person 与新的 PersonCompany 关联起来。我做 personCompany.Person = person 并调用 Session.Insert(personCompany)
  • 首先,除非您有充分的理由使用 Session.Insert,否则您应该使用 Session.SaveOrUpdate(...)。如果我没记错的话,Session.Insert 避免了很多内部缓存。
  • 对不起——我的工厂方法是插入,它调用 Session.Save() 来创建新的 PersonCompany——在它为这个人调用 Session.Merge(person) 之前(这个人不是新的) .这是两个不同的会话。
  • 在这种情况下,听起来这两个会话没有同步它们的缓存。不幸的是,这可能超出了我的专业范围。您可以尝试的一件事是确保您的会话打开和关闭正在排队。打开会话 1,创建人员 1,关闭会话 1,打开会话 2,创建公司 1,关闭会话 2,打开会话 3,创建 PersonCompany(并将人员 1 和公司 1 关联到它),关闭会话 3,打开会话 4,选择 Person 1(应该有正确的关联 PersonCompany),关闭会话 4。

标签: c# nhibernate fluent-nhibernate second-level-cache


【解决方案1】:
  1. 见上文
  2. 见上文
  3. 使用 personCompany = person.PersonCompany.FirstOrDefault() 从 Person 获取 personCompany(这将为空)

    这会将集合初始化为一个空集合

  4. 使用 Session.Save(new PersonCompany(Guid.NewGuid()) {Person = person})) 创建一个新的 PersonCompany-Entry

    将在数据库中创建一个 PersonCompany 记录

  5. 使用 person = Session.Get(person.Id) 加载人员

    只会返回缓存的人对象,所以这基本上是“什么都不做”

  6. 现在,person.PersonCompany 返回一个空列表

由于集合在第 3 步中被初始化为空集合,它只会返回那个集合。 nhibernate 不会发出另一个选择来确定是否发生了变化。如果是这样,它可能会丢弃本地更改或产生冲突,并且效率不会很高

  • session.Clear(); 作为步骤 3b
  • session.Refresh(person); 作为第 5 步

然后它按预期工作

【讨论】:

  • 当我将 session.Refresh(person) 作为第 5 步时,它会起作用。我问我,为什么需要这个,因为 Session 总是一个新打开的 Session。 NHibernate-Second-Level Cache 不应该为我做这个吗? - 当我保存一个新的 PersonCompany 然后将其添加到缓存人员的 PersonCompanies-List 中?如果没有,有没有通用的方法来解决这个问题?
  • 第二个 lvl 缓存不会神奇地更新您的对象,因为它可能不是您想要的,或者存在竞争条件等。当集合映射为“order by”、“sql”、“formula”等时,也不可能知道在哪里插入集合。应用程序中的发布 - 订阅服务通知一切以刷新他们的人将是最好的 IMO
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-01-22
  • 1970-01-01
  • 2011-08-03
  • 1970-01-01
  • 2023-03-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多