我已经实现了每个层次结构实体数据模型的表,其中包含一个抽象的Document实体和多个派生实体(Blog,Page,...)。我有使用Document实体的方法签名的存储库接口,如此
public Document Load(Guid firmId, int prettyId)
{
// the OfType<> can be OfType<Page>, OfType<Blog>, ...
var instance = (from c in _ctx.Documents.OfType<X>() where c.firm_id == firmId && c.PrettyId == prettyId select c).FirstOrDefault();
...
}
我只有一个实现存储库的类,它使用Document作为从方法返回的类型。我不需要从Document派生的不同类型的自定义实现,因为加载,插入和更新的实现细节对所有人都是相同的。我只需要识别/提供我们想要使用的方法的类型。
希望你能明白我的意思。请不要回复有关如何建模TPH的参考资料,因为我已经这样做并且模型很好。
答案 0 :(得分:1)
我实际上发现我不需要运行时检测,因为我可以在MVC控制器的编译时提供类型,与存储库(只有一个)不同,它是特定于类型的(我有PageController,BlogController等等) 。),像这样:
public virtual ActionResult Print(int prettyId)
{
//Document invoice = _repository.Load(prettyId, _docType);
Document invoice = _repository.Load<Invoice>(prettyId);
...
}
在我的存储库界面中,我现在有了这个:
// also, please comment, which one is better, this one?
T Load<T>(int prettyId) where T : Document;
T Load<T>(Guid firmId, int prettyId) where T : Document;
// or this one?
//T Load<T1>(int prettyId) where T1 : Document;
//T Load<T1>(Guid firmId, int prettyId) where T1 : Document;
并且在存储库实现中我有这个:
public T Load<T>(int prettyId) where T : Document
{
return Load<T>(AppState.FirmId, prettyId);
}
public T Load<T>(Guid firmId, int prettyId) where T : Document
{
var instance =
(from c in _ctx.Documents.OfType<T>()
where c.firm_id == firmId && c.PrettyId == prettyId
select c).FirstOrDefault();
instance.FirmReference.Load();
instance.ClientReference.Load();
instance.DocumentItems.Load();
instance.TaxStatementReference.Load();
return instance;
}
这很有效,看起来很不错。
答案 1 :(得分:0)
简单的方法是为要加载的每个特殊Document类型创建单独的方法,或者在Load方法中使用带有一些鉴别器作为参数的switch / case语句。我知道你想避免这种解决方案。在这种情况下,您应该尝试使用反射,因为在运行时提供泛型类型参数是不可能的。检查此answer以使用反射调用泛型方法。您将使用OfType调用基本查询并获取IQueryalbe的实例,该实例将用于查询的第二部分以及where条件。