Servicestack Ormlite-弱/泛型引用(例如nhibernate中的ReferencesAny) 不同的混凝土类型属性在对象字典中保存未知的基本类型外部参考

在nHibernate中,您可以将一列声明为object并将其映射为弱引用:

public virtual object TableRef{get;set;}

// then in the fluent mapping:
ReferencesAny(x => x.TableRef)

您如何在Servicestack ormlite中实现这种映射

更新 我有条件参考的需要。我想引用一个字段的3个实体。因此,当我查询数据库时,我将获得正确的参考。

public class UserEntity{

   public long Id {get;set;}
   public object MyPrimaryAnimal {get;set;}
} 

MyPrimaryAnimal也许是:CatEntityDogEntityBirdEntity

这是我能想到的最佳用例。参考薄弱。 (我拥有ormlite许可证)

谢谢

iffta 回答:Servicestack Ormlite-弱/泛型引用(例如nhibernate中的ReferencesAny) 不同的混凝土类型属性在对象字典中保存未知的基本类型外部参考

我个人不喜欢未知/未类型化的属性,因此我永远不会尝试将未知类型推入单个未类型化的字段中。我的第一个偏好是使用单一的平面混凝土结构,类似于您已经设计RDBMS表的方式,即使用具有不同列的单个平面表来捕获您要捕获的所有信息,或者在实体表本身上:

public class UserEntity
{
   public long Id { get; set; }
    //.. flattened properties of everything you want captured
}

或者如果我需要在多个表上捕获相同的信息,请使用一个具有所有要捕获的属性的类,例如:

public class UserEntity
{
   public long Id { get; set; }
   //[Reference] // Optional: Save in external Animal table
   public Animal MyPrimaryAnimal {get;set;}
}

public class Animal
{
    public string Type { get; set; } // e.g. Cat,Dog,Bird
    //.. flattened properties of everything you want captured
}

复杂类型属性会在OrmLite中自动添加,或者您可以添加[Reference]属性来注册OrmLite's POCO References support,以使数据持久保存在外部Animal表中。

对于这样的1:1映射,您需要在UserEntityAnimal类上添加FK引用

不同的混凝土类型属性

我的第二个首选项将为我要存储的每个不同属性具有不同的类型化属性,例如:

public class UserEntity
{
   public long Id { get; set; }
   public CatEntity CatEntity { get; set; }
   public DogEntity DogEntity { get; set; }
   public BirdEntity BirdEntity { get; set; }
} 

然后一切正常,将UserEntity保存在OrmLite中时,您将始终处理具体类型,这会使复杂的类型在幕后出现。

在对象字典中保存未知的基本类型

如果我绝对需要在一个字段中存储不同的实体,则可以将其存储到对象字典中,并提供类型化的包装器以持久化/检索基本实体类型,例如:

public class UserEntity
{
    public long Id { get; set; }

    [DataAnnotations.Ignore]
    public AnimalEntity MyPrimaryAnimal
    {
        get => AnimalEntity.FromObjectDictionary(AnimalRef);
        set => AnimalRef = value.ToObjectDictionary();
    }

    public Dictionary<string,object> AnimalRef { get; set; }
}

AnimalEntity将包含所有基本类型属性和一个工厂函数,以基于Type标识符返回具体的Type,例如:

public class AnimalEntity
{
    public string Type => GetType().Name;

    public static AnimalEntity FromObjectDictionary(Dictionary<string,object> props)
    {
        if (props == null) return null;
        var type = props[nameof(Type)];
        switch (type) 
        {
            case nameof(DogEntity):
                return props.FromObjectDictionary<DogEntity>();
            case nameof(CatEntity):
                return props.FromObjectDictionary<CatEntity>();
            case nameof(BirdEntity):
                return props.FromObjectDictionary<BirdEntity>();
            default:
                throw new NotSupportedException($"Unknown Animal '{type}'");
        }
    }
}

然后,您可以根据需要选择任意多个子类型:

public class CatEntity : AnimalEntity
{
    public int Id { get; set; }
    public string Cat { get; set; }
}

public class DogEntity : AnimalEntity
{
    public int Id { get; set; }
    public string Dog { get; set; }
}

public class BirdEntity : AnimalEntity
{
    public int Id { get; set; }
    public string Bird { get; set; }
}

您可以保存和检索为Typed实体,例如:

db.Insert(new UserEntity {Id = 1,MyPrimaryAnimal = new BirdEntity {Id = 1,Bird = "B"}});
db.Insert(new UserEntity {Id = 2,MyPrimaryAnimal = new CatEntity {Id = 1,Cat = "C"}});
db.Insert(new UserEntity {Id = 3,MyPrimaryAnimal = new DogEntity {Id = 1,Dog = "D"}});

var results = db.Select<UserEntity>();
var animals = results.OrderBy(x => x.Id).Map(x => x.MyPrimaryAnimal);

animals[0] //= BirdEntity 
animals[1] //= CatEntity 
animals[2] //= DogEntity 

外部参考

如果我只需要一个字段就可以在单个字段中存储对任何实体的引用,那么通常会使用a

public class UserEntity
{
    public long Id { get; set; }

    public string AnimalRef { get; set; }
}

您可以使用ServiceStack的IdUtils.CreateUrn<T> API或ToUrn<T>扩展方法:

db.Insert(new UserEntity {Id = 1,AnimalRef = 1.ToUrn<BirdEntity>() });
db.Insert(new UserEntity {Id = 2,AnimalRef = 2.ToUrn<CatEntity>() });
db.Insert(new UserEntity {Id = 3,AnimalRef = 3.ToUrn<DogEntity>() });

这将保存以下字符串引用:

urn:birdentity:1
urn:catentity:2
urn:dogentity:3

如果要加载引用,则需要一个辅助函数来分割骨灰盒,匹配类型并按ID返回实体引用。

本文链接:https://www.f2er.com/2690555.html

大家都在问