문제

나는 IRepository<T> 인터페이스, a NewsRepository 클래스와 a News 실재. 내가 실행 한 문제는 기본 저장소 클래스에 공통 방법을 추상화하려고하는 것이 었습니다.

나는 NewsRepository 특정 LINQ 표현식이 포함되어 있습니다.

내 질문입니다:

1) 기본 클래스로 어떻게 추상화합니까? public T Get(int id) 방법 제발? 내가 지금까지 한 유일한 방법은 Expression<Func<T,bool>> int 대신에, 그러나 Deos는 각 하위 클래스가 여전히 각 경우 각각의 경우 거의 동일한 표현을 전달해야하므로 공통된 행동을 실제로 추상화하지는 않습니다. n => n.id == id.

2) 업데이트 방법에 대한 기본 클래스로 어떻게 전달합니까? 하위 클래스 GetViolations 및 MAP 메소드를 제발? 솔루션이 대의원을 사용함으로써 아마도 솔루션이라고 생각하지만 구문을 컴파일 할 수 없었습니다.

이것은 단순화 된 코드 세트입니다. 실제로 여기에 표시된 업데이트가 아닌 업데이트 및 삽입을하는 저장 메소드가 있습니다.

public interface IRepository<T>
{
    T Get(int id);
    void Update(T item);
}

public class NewsRepository : IRepository<News>
{
    private Table<News> _newsTable;
    public NewsRepository(string connectionString)
    {
        _newsTable = new DataContext(connectionString).GetTable<News>();
    }

    public News Get(int id)
    {
        return _newsTable.SingleOrDefault(n => n.NewsId == id);
    }

    public void Update(News item)
    {
        var errors = item.GetRuleViolations();
        if (errors.Count > 0)
            throw new RuleException(errors);

        News dbNews = _newsTable.SingleOrDefault(n => n.NewsId == item.NewsId);
        map(dbNews, item);

        _newsTable.Context.SubmitChanges();
    }

    private void map(News dbNews, News news)
    {
        dbNews.Title = news.Title;
        dbNews.Article = news.Article;
    }
}

public class Repository<T> where T : class
{
    protected Table<T> _table;

    public Repository(Table<T> t)
    {
        _table = t;
    }

    //How do i do this??! - This doesn't compile due to T no having a NewsId
    public T Get(int id)
    {
    return _table.SingleOrDefault(n => n.NewsId == id);
    }

    //This seems to be a solution, but it's not really abstracting common behaviour as each
    //sub-class will still need to pass in the same linq expression...
    public T Get(Expression<Func<T,bool>> ex)
    {
        return _table.SingleOrDefault(ex);
    }

    public void Update(T item)
    {
        //How is it possible to pass in the GetRuleViolations and map functions to this method?
        var errors = item.GetRuleViolations();
        if (errors.Count > 0)
            throw new RuleException(errors);

        T dbNews = _table.SingleOrDefault(n => n.NewsId == item.NewsId);
        map(dbNews, item);

        _table.Context.SubmitChanges();
    }
}
도움이 되었습니까?

해결책

  1. 정말 도움이됩니다 엔티티 용 레이어 슈퍼 타입. 그들은 ID 속성을 공유합니다. ID Proprty를 대표하기 위해 표현을 다룰 필요가 없습니다. 단지 그것이 무엇인지 알게 될 것입니다.

  2. 그만큼 템플릿 메소드 패턴. 이 패턴에서 기본 업데이트는 모든 작업을 헬퍼 방법을 순서대로 수행하고 파생 된 클래스는 보호 된 추상적 도우미 방법을 구현합니다.

다른 팁

  1. L2S는 층 슈퍼 타입이나 쿼리에 인터페이스 멤버를 사용하지 않으므로 재사용이 매우 어렵습니다. 한 가지 옵션은 발현 트리를 동적으로 구축하는 것입니다. 약간 지저분하지만 기본 클래스 저장소로 분리하면 그렇게 나쁘지는 않습니다.

예는 다음과 같습니다.

public interface IEntity
{
    int Id { get; }
}

public partial class News : IEntity
{
}

public class Repository<T> where T : class, IEntity
{

    private readonly DataContext _db;

    public Repository(DataContext db)
    {
        _db = db;
    }

    public T Get(int id)
    {
        Expression<Func<T, bool>> hasId = HasId(id);
        return _db.GetTable<T>().Single(hasId);
    }

    // entity => entity.Id == id;   
    private Expression<Func<T, bool>> HasId(int id)
    {
        ParameterExpression entityParameter = Expression.Parameter(typeof (T), "entity");
        return Expression.Lambda<Func<T, bool>>(
            Expression.Equal(
                Expression.Property(entityParameter, "Id"),
                Expression.Constant(id)
                ),
            new[] {entityParameter}
            );
    }
}

또한보십시오 http://msdn.microsoft.com/en-us/library/bb397951.aspx

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