2012-10-24 2 views
3

DBContext를 사용하여 EF와 인터페이스 할 수있는 일반 저장소를 작성 중입니다. DBContext 포함 항목 포함 - 기본 키가있는 람다

나는 엔티티를 기본 키 값을 받아 반환하는 일반적인 가져 오기() 메소드가 있습니다

public class DALRepository<DALEntity> : IDisposable, IGenericRepository<DALEntity> where DALEntity : class 
{ 
private IDbSet<DALEntity> dbSet; 
private NWEntities context; 

public DALRepository() 
{ 
    context = new NWEntities(); 
    context.Configuration.LazyLoadingEnabled = false; 
    dbSet = context.Set<DALEntity>(); 
} 

다음은 간단한 get 메소드의를 - 다만 PK에서 작동 - 내가 원하는 정확히. 그래서뿐만 아니라 그들이뿐만 아니라 주문을 반환하도록 요청할 수 있습니다 단지 고객을 반환로 -

public DALEntity Get(string ID) 
{ 
    return dbSet.Find(ID); 
} 

는 지금이 소비자가 포함 목록에 통과 할 수 있도록 변경하고 싶습니다. 여기 제가 곤경에 처하게됩니다. 내가 이렇게하면 :

public DALEntity Get(string ID, IEnumerable<string> IncludeEntities = null) 
{ 
     IQueryable<DALEntity> query = dbSet; 
     query = IncludeEntities.Aggregate(query, (current, includePath) => current.Include(includePath)); 
} 

나는 IQueryable과 함께 find를 사용할 수 없다. 그리고 나는 그것을 포함 할 수 없기 때문에 Find()를 직접 찾을 수 없다. IQueryable에서 대신 lambda를 사용하면 엔티티의 PK를 사용한다고 어떻게 말할 수 있습니까? 나는 일반적인 유형이 "ID"와 같이 잘 정의 된 기본 열 이름을 가진 일부 IPkey 인터페이스를 구현해야한다고 주장하는 제네릭 제약을 가질 수 있다고 생각하지만, 구현해야하는 DBContext에 의해 생성 된 엔티티를 사용할 수 없습니다. 이 인터페이스. 필요한 경우 T4를 변경할 수 있습니다. XML 주석을 너무 많이 회피하지 않도록 이미 변경했습니다. 그러나 누구에게나 간단한 방법이 있습니까? 내가 필요한 것은 포함 목록을 받아들이는 오버로드 된 find()입니다.

내 질문은 포함하는 방법을 사용하는 방법 또는 PK를 알고있는 람다를 작성하는 방법 중 하나입니다. 매개 변수로 이러한 람다를 수신 할 수 없으므로 궁극적으로 WCF 서비스에서 사용하게됩니다.

답변

2

당신의 질문에 대답하는 종류가 있습니다.하지만 다른 사람이이 문제를 가지고있는 경우 여기 내가 한 것입니다. 동적 LINQ 물건을 사용하고 .Where()의 문자열 오버로드 된 버전을 사용했습니다. 나는 차 키를 잡아 (그리고 나의뿐만 아니라 DBContext에서이다)하는 방법을 알아 내기 위해 언급 한 링크 중 하나를 사용하고, 방법은 지금과 같다 :

public DALEntity Get(string ID, IEnumerable<string> IncludeEntities = null) 
{ 
    var set = ((IObjectContextAdapter)context).ObjectContext.CreateObjectSet<DALEntity>(); 
    var entitySet = set.EntitySet; 
    string[] keyNames = entitySet.ElementType.KeyMembers.Select(k => k.Name).ToArray(); 
    Debug.Assert(keyNames.Length == 1, "DAL does not work with composite primary keys or tables without primary keys"); 

    IQueryable<DALEntity> query = dbSet; 
    query = IncludeEntities.Aggregate(query, (current, includePath) => current.Include(includePath)); 

    query = query.Where(keyNames[0] + "= @0", ID); 
    return query.FirstOrDefault(); 
} 
0

당신은 당신의 키를 dinamycally 방법을 얻을 수가 여기에 설명되어 있습니다 : https://stackoverflow.com/a/10796471/971693 말했다되고 그건

, 나는 일부 반사 사용하지 않고하는 방법을 볼 수 없습니다 :의

public IEnumerable<DALEntity> Get(params string IDs) 
{ 
    var objectSet = objectContext.CreateObjectSet<YourEntityType>(); 
    var keyNames = objectSet.EntitySet.ElementType.KeyMembers.First(k => k.Name); 

    return dbSet.Where(m => ID.Contains((string)m.GetType().GetProperty(keyNames).GetValue(m, null)); 
} 

첫째, 문자열을 PARAMS ID를 사용하면 하나 이상의 ID를 전달할 수 있으며 문자열 배열이됩니다. 함수의 첫 번째 부분은 기본 키의 이름을 동적으로 가져 오는 것입니다.

두 번째 부분은 기본 키 값 (반영을 통해 획득 한)이 매개 변수로 수신 된 ID 배열 내에 포함 된 집합의 모든 요소를 ​​반환하는 쿼리를 만듭니다.

+0

그럼 난 처음 인정 I 돈을 이것을 이해하지 못한다. - 조금 생각 해봐! 일단 주위에 내 머리가있어 대답 할 것이다 ... ID가 정수 인 곳에서 작동하는 방법은 무엇입니까 (나는 두 가지 오버로드 된 Get()를 가짐) – RBrowning99

+0

내 대답에 몇 가지 설명을 추가했습니다. 그리고 오버로드 된 Get의 경우 int를 string으로 바꾸면 동일한 방식으로 작동합니다. –

+1

이것에 대해 고마워요. 저는 결국 그것을 사용하지 않기로 결정했지만 PK를 얻는 방법을 사용했습니다 (DBContext에서 얻는 방법을 찾은 후에). 마지막에 동적 LINQ를 사용했습니다 - 매우 간단합니다. – RBrowning99

0

개체에서 검색 할 수있는 Linq의 Single 또는 First 방법을 사용하십시오.

public DALEntity Get(string ID, IEnumerable<string> IncludeEntities = null) 
{ 
     IQueryable<DALEntity> query = dbSet; 
     query = IncludeEntities.Aggregate(query, (current, includePath) => current.Include(includePath)); 
     query = query.Single(x=>x.Id == ID); 
} 
+0

안녕하세요. 입력에 감사드립니다. 나는 당신이 제안한 것을 사용할 수 없다. 나는 첫 번째 질문에서 충분히 명확하지 않다. 왜냐하면 기본 필드 이름이 무엇인지 알지 못하기 때문이다. 우리는 이라는 id라는 속성을 정의하는 인터페이스를 구현해야한다는 제네릭 제약이 있다면 솔루션이 작동 할 것이라고 생각합니까? 컴파일러가 에 속성 ID가 있어야한다는 것을 알지 못한다면, 여러분이 가지고있는 lamda는 - 모든 클래스가 Id라는 필드를 가지고 있다고 할지라도 - woud로 작동하지 않을 것입니다. 내가 뭔가를 놓치지 않는 한. – RBrowning99

관련 문제