【问题标题】:Entity Framework Shared Core Functionality Library实体框架共享核心功能库
【发布时间】:2014-10-03 15:04:15
【问题描述】:

我正在编写一些项目,这些项目具有一些相似的核心功能,然后还有它们自己的功能。

我正在考虑制作一个类库,使用带有 Code First 的实体框架,以提供一些共享功能和与之配套的数据库表。

例如,我可能想使用类库发送一封电子邮件,然后使用实体框架登录发送电子邮件的数据库表。

这个类库将被添加到另一个项目中,该项目也使用实体框架 - 在同一个数据库中。所以现在我希望数据库“构建自己”,创建电子邮件记录表和其他一些功能,例如某种产品。

我以前没有使用过实体框架,有两个 dll 最终会导致任何混乱,因为它们都指向同一个数据库但期望不同的表?例如他们会因为没有出现在代码中而倾向于删除表吗?

如果我最终重叠也会引起问题,例如如果我想加入所有已发送电子邮件(类库实体框架)的产品(项目实体框架),我可以通过 linq 加入吗?

【问题讨论】:

  • 为什么不建立一个“数据库”项目,彻底封装您对特定数据库的所有数据访问并在项目之间共享?
  • 问题是,也许60-80%的数据会是一样的,但是每个项目的列和表会有差异——还有查询(一个项目会更复杂)比另一个)。因此,如果我要使用单个数据库项目,则每个项目都需要有冗余的表、列和查询。
  • 但是您问,“有两个 dll 最终会导致任何类型的混乱,因为它们都指向同一个数据库”。如果不同的项目对同一个表有不同的列,你怎么能指向 same 数据库?
  • 我的意思是,对于项目 A,它会有自己的 edmx 文件指向数据库 A(编译成 dll),并且它还将引用库 B - 它有自己的 edmx 文件,指向数据库 A . 我担心它会尝试删除未预料到的表,或者我无法进行任何跨 edmx 连接。也许我可以为两者指定相同的命名空间,以便它像部分文件一样构建?

标签: c# linq entity-framework


【解决方案1】:

您会希望将所有内容都集中在一个 DbContext 中。为此,您可以使用接口对每个 dll 中的实体进行分组,然后声明一个具体的 DbContext 类,将它们全部组合到您的顶级代码中。

项目1:

public interface IMyProj1DbContext : IDbContext
{
    DbSet<Person> People { get; set; }
    DbSet<Place> Places { get; set; }
}

项目2:

public interface IMyProj2DbContext : IDbContext
{
    DbSet<Customer> Customers { get; set; }
    DbSet<Order> Orders { get; set; }
}

您还需要定义公共成员的第三个项目:

public interface IDbContext
{
    int SaveChanges();
}

现在,在所有这些组合在一起的代码中,您可以声明一个实现所有接口的 DbContext 类:

public class MyDbContext : DbContext, IMyProj1DbContext, IMyProj2DbContext
{
    public DbSet<Person> People { get; set; }
    public DbSet<Place> Places { get; set; }
    public DbSet<Customer> Customers { get; set; }
    public DbSet<Order> Orders { get; set; }
}

现在,您将要编写使用两个不同上下文的代码,并且该代码将存在于每个上下文的单独 dll 中。但是你怎么能这样做呢?

public class PersonFinder
{
    public Person FindPersonByLocation(Place placeToSearch)
    {
        using (var db = new ???)
        {
            return db.People.SingleOrDefault(p => p.Location_Id == placeToSearch.Id);
        }
    }
}

你不能在这里引用具体的DbContext,因为这会导致循环依赖。关键是在运行时注入DbContext对象:

public class PersonFinder : Disposable
{
    IMyProj1DbContext _db;

    public PersonFinder(IMyProj1DbContext db)
    {
        _db = db;
    }

    public Person FindPersonByLocation(Place placeToSearch)
    {
        return _db.People.SingleOrDefault(p => p.Location_Id == placeToSearch.Id);
    }

    public void Dispose()
    {
        // ... Proper dispose pattern implementation excluded for brevity
        if (_db != null && _db is Disposable)
            ((Disposable)_db).Dispose();
    }
}

*顺便说一句,这不是注入一次性物品的最佳方式。但这样做相对安全,而且它演示了原理,没有多余的混乱。

现在您只有一个 DbContext 并且 EF 将生成和维护一个数据库,即使您拥有可以独立运行的良好逻辑域孤岛。

当您想在您编码的筒仓实体之间执行连接时,可以直接使用 MyDbContext 类。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-14
    • 1970-01-01
    • 1970-01-01
    • 2017-04-03
    相关资源
    最近更新 更多