【问题标题】:Generic Repository with Related Entities具有相关实体的通用存储库
【发布时间】:2017-02-06 22:48:22
【问题描述】:

我有一个像这样的通用存储库:

public interface IGenericRepository<TObject> where TObject : class
{
    TObject Add(TObject t);
}

public class GenericRepository<TObject> : IGenericRepository<TObject> where TObject : class
{
    private readonly DbContext context;

    public GenericRepository(DbContext context)
    {
        this.context = context;
    }

    public virtual TObject Add(TObject t)
    {
        context.Set<TObject>().Add(t);
        context.SaveChanges();
        return t;
    }
}

在我的 EF 模型中,我有 Author 和 Book,它们具有 1:N 的关系。作者有一个导航属性“书”到书,书有“作者”到作者。

然后我有一个像这样的通用服务:

public class GenericService<TObject> : IGenericService<TObject> where TObject : class
{
    private readonly IGenericRepository<TObject> context;

    public GenericService(IGenericRepository<TObject> ct)
    {
        context = ct;
    }

    public TObject Add(TObject data)
    {
        return context.Add(data);
    }
}

我有一个这样的单元测试:

[TestMethod]

public void TestAdd()
{
    var b = new Book();
    b.AuthorId = 1;
    b.Name = "Test";
    b.ISBN = "1111";
    var service = new GenericService(new GenericRepository<Book>(new MyDbEntities()));
    var newBook = service.Add(b);
    Assert.AreEqual("Author1", newBook.Author.Name);
}

问题是 newBook.Author 为 null,这意味着从 Add 方法新创建的对象没有任何相关实体。我知道此类问题的解决方案之一是使用 .include() 来包含所有相关实体,但就我而言,这是一个通用存储库,我不知道如何做到这一点。

任何帮助将不胜感激。

【问题讨论】:

    标签: c# entity-framework entity-framework-6


    【解决方案1】:

    您的问题是如何实例化 Book 对象。而不是

    var b = new Book();
    

    你应该做类似的事情

    var b = service.Create();
    

    其中 Create 是一个应该通过 EF 返回新书的方法:

    context.Set<TObject>().Create();
    

    使用 create,EF 将返回一个代理对象,因此导航属性将在附加到上下文后加载,假设您的所有引用都正常并且您的 DatabaseContext 使用延迟加载。

    检查:https://stackoverflow.com/a/31406426/1270813

    顺便问一下,验证延迟加载功能的单元测试的原因是什么?只是为了学习目的吗?根据经验,您应该测试您的代码,而不是其他框架。

    问候

    【讨论】:

    • 感谢您的建议。我会尝试 .Create() 看看它是否有效。是的,我在这里进行测试只是为了说明我遇到的问题。我真正的测试是使用 Moq 来测试逻辑,而不是框架本身。再次感谢您。
    • 但是我看不到在我的通用服务类中使用 Create() 的方法。或者我必须创建一个特定于 Book 类型的服务,并将其所有属性值分配给 Create() 返回的代理对象?
    • 您需要将该方法添加到您的服务类和通用存储库(服务最终必须调用可以访问 EF 的 repository.Create)。这是您可以访问 Entity Framework Create() 方法的唯一方法。将类添加到 db 上下文后,Entity Framework 将开始使用延迟加载附加现有对象
    猜你喜欢
    • 2017-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-29
    • 1970-01-01
    • 1970-01-01
    • 2018-07-18
    • 2019-04-17
    相关资源
    最近更新 更多