在不带EF软件包的应用程序中使用实体框架类库

时间:2018-09-26 10:33:50

标签: c# entity-framework

我想在控制台应用程序中使用我的EF类库。我已经在使用DbContext的类库中创建了一个存储库。

我的目标是在不安装Entity Framework软件包的情况下在控制台应用程序中使用此存储库。如果没有此软件包,该应用会向我显示此错误:

  

未处理的异常:System.InvalidOperationException:未找到具有不变名称'System.Data.SqlClient'的ADO.NET提供程序的实体框架提供程序。确保提供程序已在应用程序配置文件的“ entityFramework”部分中注册。有关更多信息,请参见http://go.microsoft.com/fwlink/?LinkId=260882

当我安装EF软件包时,它当然可以工作...

有人可以帮助我实现我的目标吗?

2 个答案:

答案 0 :(得分:0)

如果您有一个使用来自另一个DLL(例如EntityFramework.Dll)的类的类库,则在最终产品中,您的DLL必须能够找到该另一个DLL。

最简单的方法是将其他DLL添加到您的引用中。这将自动确保在正确部署(安装)后,另一个DLL也将被复制。

但是,很多时候您不希望DLL的用户也必须引用另一个DLL。幸运的是,只要您确保其他DLL的标识符都不在您的公共类/接口之一中,就不需要

因此,如果您的类需要EntityFramework.DLL,并且您不希望该类的用户不必引用EntityFramework.DLL,请确保没有任何公开的Entity Framework标识符。

最好的方法是使用接口。您还可以尝试在类中将使用Entity Framework的项目设置为内部。

所以代替:

public class DbSchool : DbContext
{
   ...
}

执行以下操作:

public interface IDbSchool
{
    IQueryable<Student> Students {get;}
    IQueryable<Teacher> Teachers {get;}
    IQueryable<ClassRoom> ClassRooms {get;}
    IQueryable<Course> Courses {get;}
}

internal class DbSchool : DbContext, IDbSchool
{
     internal DbSet<Student> Students {get; set;}
     internal DbSet<Teachter> Teachers {get; set;}
     ...

     // Explicit interface implementation of IDbSchool:
     IQueryable<Student> IDbSchool.Students {get => this.Students;}
     IQueryable<Teacher> IDbSchool.Teachers {get => this.Teachers;}
     ...
}

只要您在DLL中编写代码,就可以使用Entity Framework中的所有内容,毕竟,您的DLL引用了它。

您的DLL用户没有引用实体框架,因此他们不能使用诸如DbContextDbSet之类的标识符。但是,如果他们引用您的DLL,则可以使用标识符,例如StudentTeacherCourse,当然也可以是IDbSchool

但是我的用户如何创建DbSchool类的对象?

答案:他不能。因此,您必须创建一个返回IDbSchool的工厂函数:

public static class SchoolFactory
{
    public static IDbSchool CreateSchoolContext(...)
    {
         return new DbSchool(...);
    }
}

用法:

using (IDbSchool dbSchool = SchoolFactory.CreateSchoolContext(...))
{
      var teachersWithStudents = dbSchoolTeachers
          .Select(teacher => new
          {
              Id = teacher.Id,
              Name = teacher.Name,
              Students = teacher.Students.Select(student => new
              {
                  Id = student.Id,
                  Name = student.Name,
              })
              .ToList(),
          })
          .Where(teacher => teacher.Students.Any());
}

注意:由于您要正确处置DbSchool,因此IDbSchool应该源自IDisposable

public interface IDbSchool, IDisposable {...}

答案 1 :(得分:0)

您的库的app.config文件包含运行时设置。它们没有效果,因为运行时设置必须来自可执行文件的配置文件。

只需将它们复制到可执行项目的app.config中。

如果您想朝相反的方向前进,则可以使用安装脚本为库创建一个NuGet包,以修改目标的app.config。这样,没有人会仅仅为了在项目中使用它而处理库的内部需求。