实体框架共享核心功能库

时间:2014-10-03 15:04:15

标签: c# linq entity-framework

我正在编写一些项目,这些项目具有一些相似的核心功能,然后是其自身的功能。

我正在考虑使用Entity Framework和Code First创建一个类库,以便提供一些共享功能和随之而来的数据库表。

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

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

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

如果我最终重叠,它会导致问题,例如如果我想在已发送电子邮件(类库实体框架)的所有产品(项目实体框架)上进行加入,我是否可以通过linq进行加入?

1 个答案:

答案 0 :(得分:0)

您希望将所有内容保存在一个DbContext中。您可以通过使用接口对每个dll中的实体进行分组来实现此目的,然后声明一个具体的DbContext类,它将它们全部组合在您的顶级代码中。

PROJECT1:

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

Project2的:

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将生成并维护一个单独的数据库,即使你有一个可以独立运行的好的逻辑域孤岛。

如果要在silo实体之间执行连接,则代码可以直接使用MyDbContext类。