我的上下文是否与我的存储库耦合?

ben*_*itr 0 c# entity-framework inversion-of-control unity-container repository-pattern

学习实体框架,存储库和IOC,我想要实现的是实现存储库模式,以便更改我的数据源提供程序.

请从开源项目中查看此示例:

namespace MyApp.Domain.Interfaces
{
    public interface IEFContext : IDisposable
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

EFContext(实现IEFContext)

namespace MyApp.Data.Context
{
    public class EFContext : DbContext, IEFContext
    {
        public const string DBConnectionName = @"MyDBName";

        public EFContext() : base(DBConnectionName)      
        {
        }

        public DbSet<Member> Member { get; set; }
    }
}
Run Code Online (Sandbox Code Playgroud)

IMemberRepository

namespace MyApp.Domain.Interfaces.Repositories
{
    public interface IMemberRepository
    {
        Member GetUser(string username);
    }
}
Run Code Online (Sandbox Code Playgroud)

MemberRepository(实现IMemberRepository)

namespace MyApp.Data.Repositories
{
    public class MemberRepository : IMemberRepository
    {
        private readonly EFContext _context;

        public MemberRepository(IEFContext context)
        {
            _context = context as EFContext;
        }

        // update
        public Member GetUser(string username)
        {
            return _context.Member.SingleOrDefault(name => name.UserName.ToUpper().Contains(username.ToUpper()));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我使用Unity的应用程序控制台

控制台应用

namespace MyApp.ConsoleApp
{
    public class Program
    {
        static void Main(string[] args)
        {
            var container = new UnityContainer();
            container.RegisterType<IEFContext, EFContext>();
            container.RegisterType<IMemberRepository, MemberRepository>();
            var repository = container.Resolve<MemberRepository>();
            var user = repository.GetUser("johnDoe");
            Console.WriteLine(user.Email);
            Console.ReadLine();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我的问题如下:

如果我决定添加新的上下文,例如:

namespace MyApp.Data.Context
{
    public class EFContext2 : DbContext, IEFContext
    {
        public const string DBConnectionName = @"MyNewDBName";

        public EFContext2() : base(DBConnectionName)      
        {
        }

         public DbSet<Member> Member { get; set; }
    }
}
Run Code Online (Sandbox Code Playgroud)

我应该只需要改变依赖性:

namespace MyApp.ConsoleApp
{
    public class Program
    {
        static void Main(string[] args)
        {
            ...
            container.RegisterType<IEFContext, EFContext2>();
            ...         
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

但在这个例子中,我的MemberRepository与我的第一个上下文松散耦合.因此,如果我必须更改我的上下文,我还必须更改我的存储库.

我很乐意对此有所了解.亲切的问候

Err*_*Efe 5

but in this example my MemberRepository is loosely-coupled with my first context. So if I have to change my Context I must also change my repository.
Run Code Online (Sandbox Code Playgroud)

是的,但它是一个改变:

private readonly EFContext _context;  
Run Code Online (Sandbox Code Playgroud)

private readonly IEFContext _context;  
Run Code Online (Sandbox Code Playgroud)

而不是在你的构造函数上强制转换:

public MemberRepository(IEFContext context)            
{                
    _context = context;            
}
Run Code Online (Sandbox Code Playgroud)

现在,您可以注入任何实现IEFContext的具体上下文.

试想一下:你试图用依赖注入做的事情就是注入依赖关系.但是,你是怎么做的?好吧,你通过概括那些依赖关系来做到这一点.我的意思是,您希望能够使用不同的上下文,然后使用接口IEFContext而不是具体的上下文.这就是你的构造函数需要一个接口的原因.

但是,这是第一部分,知道,代码的问题在于你说的时候

_context = context as EFContext;
Run Code Online (Sandbox Code Playgroud)

你正在向下转换界面并说:这个界面是一个EFContext.你失去了普遍性.知道什么时候你尝试注入一个,比如SQLContext,你将无法做到,因为虽然它和IEFContext不是EFContext.这就是为什么你删除该as EFContext部分,然后让

_context = context;
Run Code Online (Sandbox Code Playgroud)

现在至于第二部分,一般而且期待和接收界面只是第一部分.您现在需要告诉编译器您期望通用上下文IEFContext,但您还需要告诉他,无论您收到哪个上下文,您都应该能够使用GetUsers.这就是你的界面发挥作用的地方.您知道public Member GetUser{}在界面中声明属性强制并保证无论哪个上下文到达您都能够获得您的用户.

我希望这有点简单易懂.祝好运.