Table-具有相同 ID 的每个子类对象在缓存中发生冲突

Table-per-subclass objects with same id collide in cache

我需要使用 Fluent NHibernate 映射遗留 table。我无法控制 table 结构。

table 看起来像这样:

TypeId   ObjectId   Data
10       1          ...   //Cat 1
10       2          ...   //Cat 2
20       1          ...   //Dog 1
30       1          ...

我正在尝试使用 table-per-subclass 结构来映射它,使用 TypeId 的鉴别器值。

public abstract class Animal
{
    public virtual int ObjectId { get; set; }
    public virtual string Data { get; set; }
}

public class AnimalMap : ClassMap<Animal>
{
    public AnimalMap()
    {
        Table("MyAnimals");
        Id(x => x.ObjectId);
        Map(x => x.Data);
        DiscriminateSubClassesOnColumn("TypeId")
            .AlwaysSelectWithValue();
    }
}

public class Cat : Animal
{
}

public class CatMap : SubclassMap<Cat>
{
    public CatMap()
    {
        DiscriminatorValue("10");
    }
}

public class Dog : Animal
{
}

public class DogMap : SubclassMap<Dog>
{
    public DogMap()
    {
        DiscriminatorValue("20");
    }
}

当我尝试在 Dog 1 之后加载 Cat 1 时出现问题,反之亦然。

var a = session.Get<Dog>(1); //Dog1
var b = session.Get<Cat>(1); //null

如果我在抓到第二只动物之前驱逐了第一只动物,它就成功了。

var a = session.Get<Dog>(1); //Dog1
session.Evict(a);
var b = session.Get<Cat>(1); //Cat1

当我将 DogCat 映射到我的 AnimalHome class 时,出现以下异常:

Unable to cast object of type 'MyNamespace.Dog' to type 'MyNamespace.Cat'.

这让我相信缓存不会根据类型区分 DogCat。它只是将其视为 Animal 1 并且 Cat 1 等于 Dog 1

我能否以某种方式让缓存考虑实际的子class? 或者,如果使用 table-per-subclass 结构不可能做到这一点,我应该如何映射这个 table?

我通过放弃鉴别器解决了这个问题。 Where 映射更适合我的情况,因为我实际上不需要在我的代码中将 DogCat 视为 Animal。 我仍然通过继承 Animal 相关的映射将代码重复保持在最低限度。

public class AnimalMap<T> : ClassMap<T>
    where T : Animal
{
    public AnimalMap()
    {
        Table("MyAnimals");
        Id(x => x.ObjectId);
        Map(x => x.Data);
    }
}

public class CatMap : AnimalMap<Cat>
{
    public CatMap()
    {
        Where("TypeId = 10");
    }
}

缓存现在知道 Cat 不是 Dog