具有相同id的表每子类对象在高速缓存中发生冲突

时间:2017-01-03 10:28:14

标签: c# caching nhibernate fluent-nhibernate table-per-subclass

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

表格如下:

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

我正在尝试使用每个子类的表结构使用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");
    }
}

当我尝试在Cat 1之后加载Dog 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课程时,我收到以下异常:

  

无法投射&#39; MyNamespace类型的对象。&#39;输入   &#39; myNameSpace对象的&#39;

这让我相信缓存并没有区分DogCat的类型。它只是将其视为Animal 1 Cat 1等于Dog 1

我可以以某种方式使缓存考虑实际的子类吗? 或者,如果每个子类的表结构不可能实现这一点,那么我该如何处理这个表的映射?

1 个答案:

答案 0 :(得分:1)

我通过抛弃判别者来解决这个问题。 在我的情况下,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