在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
也许是:CatEntity
,DogEntity
或BirdEntity
。
这是我能想到的最佳用例。参考薄弱。 (我有ormlite许可证)
谢谢
我个人不喜欢未知/未类型化的属性,因此我永远不会尝试将未知类型推入单个未类型化的字段中。我的首选是使用单个平面混凝土结构,类似于已经设计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
}
Complex Type属性在OrmLite中会自动被blob,或者您可以添加[Reference]
属性来登记OrmLite's POCO References support以使数据持久保存在外部Animal
表中。
您需要在
UserEntity
或Animal
类上为这样的1:1映射添加FK引用
我的第二个首选项将为我要存储的每个不同属性具有不同的类型化属性,例如:
public class UserEntity
{
public long Id { get; set; }
public CatEntity CatEntity { get; set; }
public DogEntity DogEntity { get; set; }
public BirdEntity BirdEntity { get; set; }
}
然后一切正常,在OrmLite中保存UserEntity
时,您将始终处理具体类型,这会使幕后复杂的类型变得模糊不清。
如果绝对需要在一个字段中存储不同的实体,则将其存储到对象字典中,并提供一个类型化的包装器以持久化/检索基本实体类型,例如:
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; }
}
您可以将其保存和检索为类型化实体,例如:
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返回实体引用。