具有实体框架和存储库模式的每个层次结构实现的表

时间:2010-11-28 18:07:31

标签: entity-framework entity-framework-4 repository-pattern

我已经实现了每个层次结构实体数据模型的表,其中包含一个抽象的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的参考资料,因为我已经这样做并且模型很好。

2 个答案:

答案 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条件。