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

发布于 2024-10-04 15:15:06 字数 583 浏览 2 评论 0原文

我已经使用抽象文档实体和多个派生实体(博客、页面等)实现了每个层次结构的表实体数据模型。我有使用 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 的参考资料,因为我已经这样做了并且建模得很好。

I've implemented table per hierarchy Entity Data Model with an abstract Document entity and multiple derived entities (Blog, Page, ...). I have repository interface with method signatures using Document entity like this

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();
    ...
}

I only have one class that implements the repository and it is using Document as the type to return from methods. I don't need custom implementations for different types that derive from Document because the implementation specifics for loading, inserting and updating are the same for all. I just need to identify/provide the type to the methods that we want to work with.

Hopefully you will understand what I mean. Please do not reply with references on how to model the TPH because I've already done that and it is modeled fine.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

苄①跕圉湢 2024-10-11 15:15:06

我实际上发现我不需要运行时检测,因为我可以在 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;
}

这有效并且看起来不错。

I've actually discovered that I don't need runtime detection because I can provide type at compile time in my MVC controllers, which unlike the repository (which is only one) are type specific (I have PageController, BlogController, etc.), like this:

public virtual ActionResult Print(int prettyId)
{
    //Document invoice = _repository.Load(prettyId, _docType);
    Document invoice = _repository.Load<Invoice>(prettyId);
    ...
}

In my repository interface I now have this:

// 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;

and in repository implementation I have this:

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;
}

This works and looks kinda nice.

不离久伴 2024-10-11 15:15:06

简单的方法是为要加载的每个特殊文档类型创建单独的方法,或者使用 switch / case 语句以及一些鉴别器作为 Load 方法中的参数。我知道您想避免这样的解决方案。在这种情况下,您应该尝试使用反射,因为不可能在运行时提供泛型类型参数。检查此答案以通过反射调用泛型方法。您将使用 OfType 调用基本查询并获取 IQueryalbe 的实例,该实例将用于带有 where 条件的查询的第二部分。

Simple way is to create separate method for each special Document type you want to load or to use switch / case statements with some discriminator as parameter in Load method. I understand you want to avoid such solution. In that case you should try to use reflection because providing generic type parameter at runtime is not possible. Check this answer for calling generic method with reflection. You will invoke the base query with OfType and get the instance of IQueryalbe which will be used in for second part of query with where conditions.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文