如何使用存储库模式访问EF中的导航属性

时间:2015-03-31 23:06:12

标签: c# entity-framework repository-pattern

上下文:ASP.NET Web应用程序

Base Repository(抽象类)实现所有其他存储库继承所需的基本功能: 即 -PersonRepo -AddressRepo

修改 您在哪里放置查询多个db表的代码,其中一些不直接与相应存储库中的导航属性相关?

现在,访问导航属性的最佳方法是什么? 使用存储库模式时非常麻烦。 如果没有一个方便的解决方案,我将坚持我的旧DAL层内部的所有内容,并直接使用DbContext。

我刚刚提出了一个临时解决方案,用于访问PersonRepository实现中的导航属性:

public Person InsertNewPersonWithAddress(Person p, Address addr)
        {
            this.Insert(p); // insert person
            var ar = new AddressRepository(this.ctx);
            ar.Insert(addr);  // insert address
            this.Addresses(p).Add(addr);  // add address to person

            return p;
        }

        /* Navigation Properties */ 
        ICollection<Address> Addresses(Person p)
        {
            return ctx.Entry<Person>(p).Collection<Address>("Addresses").CurrentValue;
        }

Base Repository 类实现以下接口

public interface IRepository<T> where T : class
    {
        IQueryable<T> All();
        IQueryable<T> FindBy(Expression<Func<T, bool>> predicate);
        T Insert(T entity);
        IEnumerable<T> InsertMultiple(IEnumerable<T> items);
        T Delete(T entity);
        IEnumerable<T> DeleteMultiple(IEnumerable<T> items);
        T Update(T entity);
        IEnumerable<T> UpdateMultiple(IEnumerable<T> items);
        void Save();
    }

DB-设计:

人 - &gt; PersonAddress(联结表)&lt; - 地址

针对此问题的任何智能解决方案?

1 个答案:

答案 0 :(得分:1)

你正在考虑这个错误的方法。 navigation属性是Entity的属性,而不是Repository的属性。您不需要为导航属性实例化存储库,它可以直接添加到实体。

public Person InsertNewPersonWithAddress(Person p, Address addr)
{
    p.Address = addr;
    this.Insert(p); // insert person

    return p;
}

现在,如果您要插入新的Person,但希望将其附加到现有的Address(而不是插入两者的新副本),则可以将AddressId FK公开为Person实体上的属性,并传入FK值以进行链接。在任何一种情况下,此存储库都不需要访问另一个存储库。