【问题标题】:BaseDbContext with shared entitiesBaseDbContext 与共享实体
【发布时间】:2016-09-01 16:00:45
【问题描述】:

我有一种情况,我认为这很简单,但事实证明很困难。

我有一个数据库,目前有两个不同的 Web 应用程序在使用它。每个应用程序都有专门用于该应用程序的表,同时还有几个共享表,例如 ApplicationUser 表。

我想要做的是拥有一个包含所有共享实体的基本上下文,并具有从基本上下文派生的应用程序特定上下文。对于应用程序上下文,许多共享实体将具有派生的应用程序特定实体,该实体具有额外的导航属性。

为了清楚起见,我将尝试说明:

共享库中的BaseContext

public class BaseContext : DbContext
{
    public DbSet<ApplicationUser> ApplicationUsers { get; set; }
}

App1 中的 App1Context

public class App1Context : BaseContext
{
    public new DbSet<App1User> ApplicationUsers { get; set; }
}

public class App1User: ApplicationUser
{ 
    //Navigation property specific to App1
    public virtual ICollection<SomeApp1Entity> SomeApp1Entity_Creator { get; set; } 
}

App2 中的 App2Context

public class App2Context : BaseContext
{
    public new DbSet<App2User> ApplicationUsers { get; set; }
}

public class App2User: ApplicationUser
{
    //Navigation property specific to App2
    public virtual ICollection<SomeApp2Entity> SomeApp2Entity_Creator { get; set; } 
}

BaseContext 有一个 ApplicationUser 的 dbset。

App1Context 有一个派生自 ApplicationUser 的 App1User 数据库集。

App2Context 有一个 App2User 的 dbset,它也派生自 ApplicationUser。

我需要特定于应用的用户实体,因为 App1User 可能具有指向未共享实体的导航属性,并且仅适用于 App1。 App2User 也是如此。

我想要 BaseContext 的主要原因是我可以拥有一个 SharedService,它使用这个上下文并拥有我所有的 ApplicationUser 方法用于 CRUD。

我尝试了几种变体,因此如有必要,我可以提供更多信息,我只是不想让这个问题太长,试图解释我尝试过的所有内容。

我知道我想要 BaseContext 的 dbset,以便我可以拥有共享服务。在 App1Context 中构建模型时,我尝试忽略 ApplicationUser,因为我认为会使用 App1User,但这不起作用。当我这样做时,它说没有键集(因为它忽略了具有键的基类,而不是在派生类中拾取它)。当我不忽略时,我会收到关于鉴别器列的错误。

我的第一个问题是,我用这种方法完全是在浪费时间吗? Entity Framework 6.3 甚至可以吗?

如果可能,我该如何以不同的方式找到解决方案?

另外,让我补充一下,我首先使用代码,但不担心迁移。数据库已经存在,对数据库的所有更改都在那里进行,然后在 C# 代码中相应地实现。

【问题讨论】:

  • 这可能吗:public class BaseContext: DbContext { DbSet&lt;ApplicationUser&gt; Users { get; set; } public class App1Context: BaseContext{} and public class App2Context: BaseContext{}。通常我们是否从用户实体中指定所有导航属性?通常其他实体将具有 User 的导航属性来设置诸如 UpdatedBy、CreatedBy 等关系
  • 如果你能格式化你的问题会很棒
  • 通用基类会起作用吗? BaseContext&lt;TUser&gt; : DbContext where TUser : ApplicationUserApp1Context : BaseContext&lt;App1User&gt;.
  • @Developer 我得到“无效的列名'鉴别器'。”错误。这似乎是因为我在 App1User 类中继承了 ApplicationUser,而实体框架希望将其视为每个类型的表。我尝试在派生类上使用 [NotMapped] 属性,但是我无法访问 App1User 或 App2User 特定的反向导航属性。有什么想法吗?
  • @RichardDeeming 当我需要一个使用基本上下文来保存共享 CRUD 方法的服务时,我不知道如何实现它。我的共享服务需要使用 BaseContext,但这需要发送一个 Context,这显然是行不通的... BaseContext ...我尝试做一个 BaseContext 和一个 SharedContext : BaseContext,但我仍然遇到了刚刚向开发人员描述的相同错误。

标签: c# asp.net inheritance entity-framework-6 dbcontext


【解决方案1】:

我不确定这是否是您要找的:

我将共享上下文和实体保存在一个单独的库中 - SharedDbContext 命名空间:

namespace SharedDataContext
{
    public class BaseDbContext : DbContext
    {
        public BaseDbContext() : base("CFConnection")
        { }

        public DbSet<ApplicationUser> ApplicationUsers { get; set; }

    }

    public partial class ApplicationUser
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
}

并创建了两个应用程序 - WebApplication1WebApplication2

WebApplication1 - App1Context - 有自己的实体 Country 与共享 ApplicationUser

namespace WebApplication1
{
    public class App1Context : BaseDbContext
    {
        public DbSet<Country> Countries { get; set; }
    }

    public class Country
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int ApplicationUserId { get; set; }
        public ApplicationUser ApplicationUser { get; set; }
    }
}

WebApplication1 - App2Context - 拥有自己的实体 City 与共享 ApplicationUser

namespace WebApplication2
{
    public class App2Context : BaseDbContext
    {
        public DbSet<City> Cities { get; set; }
    }

    public class City
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int ApplicationUserId { get; set; }
        public ApplicationUser ApplicationUser { get; set; }
    }

}

来自 WebApplication2 的示例控制器和结果:

namespace WebApplication2.Controllers
{
    public class CityController : ApiController
    {
        public IEnumerable<City> Get()
        {
            IEnumerable<City> cities;
            using (var context = new App2Context())
            {
                cities = context.Cities.Include(c => c.ApplicationUser).ToList();
            }
            return cities;
        }
    }
}

共享实体详细信息的结果:

我建议不要在共享实体中保留与上下文相关的导航,而是从另一端查询它 - 如果您需要获取“User1”的城市,请查询DbSet&lt;City&gt; Cities ApplicationUserId == 1如果我们在 ApplicationUser 中包含 ICollection&lt;City&gt;,这会很容易,我不知道在这种情况下如何实现

【讨论】:

  • 感谢您的模型!我实际上希望做你建议不要做的事情。拥有一个具有 App1 特定 ICollections 的 App1User。 App1User 将派生自 ApplicationUser。但是,像您一样,我不确定如何在可行的情况下执行此操作。这似乎是直截了当的,但 EF 不喜欢它。我宁愿从另一端查询,也不愿为每个应用程序重复所有共享代码,所以我将继续按照您的建议实施。非常感谢您的回复。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-20
  • 1970-01-01
  • 2022-11-17
  • 2017-07-08
  • 1970-01-01
  • 2013-02-04
相关资源
最近更新 更多