0

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

请从一个开源项目中查看这个示例:

namespace MyApp.Domain.Interfaces
{
    public interface IEFContext : IDisposable
    {
    }
}

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; }
    }
}

IMemberRepository

namespace MyApp.Domain.Interfaces.Repositories
{
    public interface IMemberRepository
    {
        Member GetUser(string username);
    }
}

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()));
        }
    }
}

这是我使用 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();
        }
    }
}

我的问题如下:

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

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

        public EFContext2() : base(DBConnectionName)      
        {
        }

         public DbSet<Member> Member { get; set; }
    }
}

我只需要更改依赖项,例如:

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

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

我很乐意听取您对此的看法。亲切的问候

4

1 回答 1

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.

是的,但它是从一行更改:

private readonly EFContext _context;  

private readonly IEFContext _context;  

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

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

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

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

但是,这是第一部分,知道,你的代码的问题是当你说

_context = context as EFContext;

你正在向下转换接口并说:这个接口是一个 EFContext。你失去了一般性。知道当您尝试注入 SQLContext 时,您将无法注入,因为尽管它是 IEFContext,但它不是 EFContext。这就是为什么您移除as EFContext零件并让

_context = context;

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

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

于 2012-09-22T16:42:03.717 回答