문제

새로운 asp.net 웹 프로젝트를 시작할 준비를 하고 있으며 LINQ-to-SQL을 사용할 예정입니다.나는 다음에서 찾은 일부 정보를 사용하여 데이터 영역 설정을 가져오는 약간의 작업을 수행했습니다. 마이크 해들로우 인터페이스와 제네릭을 사용하여 데이터베이스의 각 테이블에 대한 저장소를 생성합니다.처음에는 이것이 흥미로운 접근 방식이라고 생각했습니다.그러나 이제는 기본 Repository 클래스를 생성하고 이를 상속하여 액세스해야 하는 테이블에 대한 TableNameRepository 클래스를 생성하는 것이 더 합리적일 수 있다고 생각합니다.

어떤 접근 방식을 사용하면 깔끔하게 테스트 가능한 방식으로 테이블 관련 기능을 추가할 수 있나요?다음은 참조용 저장소 구현입니다.

public class Repository<T> : IRepository<T> where T : class, new()
{
    protected IDataConnection _dcnf;

    public Repository()
    {
        _dcnf = new DataConnectionFactory() as IDataConnection;
    }

    // Constructor injection for dependency on DataContext 
    // to actually connect to a database
    public Repository(IDataConnection dc)
    {
        _dcnf = dc;
    }

    /// <summary>
    /// Return all instances of type T.
    /// </summary>
    /// <returns>IEnumerable<T></returns>
    public virtual IEnumerable<T> GetAll()
    {
        return GetTable;
    }

    public virtual T GetById(int id)
    {
        var itemParam = Expression.Parameter(typeof(T), "item");
        var whereExp = Expression.Lambda<Func<T, bool>>
            (
                Expression.Equal(
                    Expression.Property(itemParam, PrimaryKeyName),
                    Expression.Constant(id)
                ), new ParameterExpression[] { itemParam }
            );
        return _dcnf.Context.GetTable<T>().Where(whereExp).Single();
    }

    /// <summary>
    /// Return all instances of type T that match the expression exp.
    /// </summary>
    /// <param name="exp"></param>
    /// <returns>IEnumerable<T></returns>
    public virtual IEnumerable<T> FindByExp(Func<T, bool> exp)
    {
        return GetTable.Where<T>(exp);
    }

    /// <summary>See IRepository.</summary>
    /// <param name="exp"></param><returns></returns>
    public virtual T Single(Func<T, bool> exp)
    {
        return GetTable.Single(exp);
    }

    /// <summary>See IRepository.</summary>
    /// <param name="entity"></param>
    public virtual void MarkForDeletion(T entity)
    {
        _dcnf.Context.GetTable<T>().DeleteOnSubmit(entity);
    }

    /// <summary>
    /// Create a new instance of type T.
    /// </summary>
    /// <returns>T</returns>
    public virtual T Create()
    {
        //T entity = Activator.CreateInstance<T>();
        T entity = new T();
        GetTable.InsertOnSubmit(entity);
        return entity;
    }

    /// <summary>See IRepository.</summary>
    public virtual void SaveAll()
    {
        _dcnf.SaveAll();
    }

    #region Properties
    private string PrimaryKeyName
    {
        get { return TableMetadata.RowType.IdentityMembers[0].Name; }
    }

    private System.Data.Linq.Table<T> GetTable
    {
        get { return _dcnf.Context.GetTable<T>(); }
    }

    private System.Data.Linq.Mapping.MetaTable TableMetadata
    {
        get { return _dcnf.Context.Mapping.GetTable(typeof(T)); }
    }

    private System.Data.Linq.Mapping.MetaType ClassMetadata
    {
        get { return _dcnf.Context.Mapping.GetMetaType(typeof(T)); }
    }
    #endregion
}
도움이 되었습니까?

해결책

종속성 주입(성?)을 사용하여 리포지토리를 생성하는 것처럼(다른 캐시 등으로 래핑할 수 있도록) 구체적인 유형을 사용하는지 여부는 중요하지 않다고 제안하고 싶습니다. 그러면 코드베이스는 다음과 같습니다. 어떤 방식으로든 당신이 해낸 것이 더 현명하지는 않습니다.

그런 다음 DI에 저장소를 요청하세요.예:성의 경우:

public class Home {
  public static IRepository<T> For<T> {
    get {
      return Container.Resolve<IRepository<T>>();
    }
  }
}

개인적으로, 나는 당신이 필요를 찾을 때까지 유형을 마무리하지 않을 것입니다.

질문의 나머지 절반은 테스트 및 캐싱 목적으로 IRepository의 메모리 구현을 쉽게 제공할 수 있는지 여부입니다.이를 위해 linq-to-objects가 느려질 수 있고 다음과 같은 것을 찾을 수 있으므로 조심하겠습니다. http://www.codeplex.com/i4o 유용한.

다른 팁

모든 테이블에 대해 저장소를 생성해서는 안 됩니다.
대신 도메인 모델에 존재하는 모든 '엔터티 루트'(또는 집계 루트)에 대한 저장소를 만들어야 합니다.패턴에 대해 자세히 알아보고 여기에서 실제 예제를 볼 수 있습니다.

http://deviq.com/repository-pattern/

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top