1

여러분!Linq2Sql에서 사용자 정의 유형을 이해하는 방법은 무엇입니까?

'도메인 : IUser, IAddressBook, IComment'등의 문제를 나타내는 인터페이스가 있다고 가정 해 보겠습니다. 다음과 같이 IUser가 정의되어 있다고 가정 : 예를 들어, 난 단지 언급 계약을 사용하여 내 응용 프로그램에서

public interface IUser : IAmIdentifiedEntity<int>, IHaveName 
{ 
    string FullName { get; set; } 
    string Email { get; set; } 
    bool ReceiveNotification { get; set; } 
} 

public interface IHaveName 
{ 
    string Name { get; set; } 
} 

을 :

public IUser GetUser(string userName) 
{ 
    return Warehouse.GetRepository<IUser>().GetAll() 
     .First(u => u.Name == userName); 
} 

당신이 볼 수 있듯이

, 나는 데이터를 얻기 위해 약간의 게이트웨이를 사용하고 있습니다. Repository '메서드 GetAll()IQueryable<TEntity>을 반환하므로 일부 복잡한 쿼리를 작성하고 지연로드의 모든 이점을 사용할 수 있습니다. 내가 그것을 소개 할 때, 나는 Linq2Sql의 어플라이언스에 대해 미래에 생각했다.

얼마 동안 클라이언트 코드를 개발하는 동안 우리는 데이터 저장소의 '메모리 내 (in-memory)'구현을 사용하고있었습니다. 그래서 모든 것이 잘 작동합니다. 그러나 이제 도메인을 SQL Server에 바인딩 할 차례입니다. 그래서 Linq2Sql에 모든 인프라를 구현하기 시작했습니다 ... 그리고 간단한 솔루션 (Fredrik Kalseth의 article에서 영감을 얻었습니다)이 첫 번째 예외를 얻었을 때, 나는 그 아이디어의 모든 슬픔을 깨달았습니다. 여기에 함축이 있습니다. 여기

public partial class USER : IUser 
{ 
    int IHaveID<int>.ID 
    { 
     get { return USERID; } 
    } 

    string IHaveName.Name 
    { 
     get { return USERNAME; } 
     set { USERNAME = value; } 
    } 

    string IUser.FullName 
    { 
     get { return USERFULLNAME; } 
     set { USERFULLNAME = value; } 
    } 

    // ... same approach for other properties 
} 

그리고 - 예외 : IUser

Exception: System.NotSupportedException: 
    The member 'Data.IHaveName.Name' has no supported translation to SQL. 

이 분명 예외는 - Linq2Sql 공급자가 외부 인터페이스를 이해하지 않지만, 어떻게 그것을 해결해야 하는가? 이 도메인의 모든 인터페이스 현재 코드 사용을 나누기 때문에

Expression<Func<string>> IHaveName.Name 
{ 
    get { return (() => USERNAME); } 
    set { USERNAME = value(); } 
} 

하고 또한 내가 종교적 신념 Expression<Func<int>>int을 대체 할 수 없습니다 :

: 내가 좋아하는 Linq.Expression를 반환하는 도메인 인터페이스를 변경할 수 없습니다

어쩌면, 나는

당신이 그것에 의견을 제공 할 수 있습니다 ... 그것의 내부 하위 AST와 함께 IUser.SomeProperty의 '쿼리에서 AST 통화를 건너 뛰고 교체하는 사용자 정의 식 방문자를 작성해야?

업데이트. 여기에 Repository 구현에 대해 뭔가 작성해야합니다. 내 예에서

public IQueryable<TEntity> GetAll() 
{ 
    ITable table = GetTable(); 
    return table.Cast<TEntity>(); 
} 

protected ITable GetTable() 
{ 
    return _dataContext.GetTable(_implType); 
} 

, TEntity <=> IUser 내가 OP는 모두 문제가 related question을 발견했습니다 2._implType <=> typeof(USER)

UPDATE : GetAll() 소스 봐 콘크리트 ORM의 실체와 그것의 사이에 다리를 필요 도메인 엔티티. 흥미로운 사실을 발견했습니다. the answer : 작성자가 표현 방문자를 생성하도록 제안 했으므로 엔티티 간 변환이 수행됩니다 (ORM < => 도메인).

+0

새로운 제안이 있으십니까? – ajukraine

답변

0

내 문제를 해결하는 방법을 찾았습니다. 오늘 나는 "Linq를 사용하는 고급 도메인 모델 쿼리"라는 멋진 series of post을 발견했습니다. 저자는 엔티티를 다루기 위해보다 편리한 (예쁜) 람다 구문을 지원하는 방법을 제시합니다. 그리고 그는 Expression Tree 변환을 사용합니다. 그래서 나는이 접근법을 따를 것이고, 성공한다면 나는 (아마도 내 블로그를 통해)보다 상세한 대답을 게시 할 것이다.

그 생각에 대해 어떻게 생각하십니까? Expression Provider를 구현하는 데 시간을 할애해야합니까?

업데이트. 커스텀 Expression vistior에 실패했습니다 - 표현식 트리를 통해 많은 변환이 필요합니다. 그래서 나는 모든 Linq 로직을 "스토리지"클래스로 옮겼다. 복잡한 쿼리와 지속성 관리를 캡슐화했다.

0

Name의 속성을 Column 속성으로 장식하십시오. Linq2SQL과 함께 사용하는 다른 유형과 동일하게 지정하십시오.

+0

'Name'을 쓸 때'IHaveName'을 원하셨습니까? – ajukraine

+0

아니, 이름, 실제 클래스 Linq2SQL 속성을 찾는 것입니다 뜻. –

+0

... 일부 경우에는이 문제를 해결하는 인터페이스가 아닌 기본 클래스의 속성에있을 수 있습니다. –

0

이것은 잘 알려진 문제로, SQL 문자열 명령으로 캐스팅 할 수없는 논리로 IQueryable을 실행하려고 시도 할 때마다 LINQ-to-SQL 자체가이 오류를 발생시킵니다.

이 문제는 IQueryable - 지연 실행의 특성 때문에 발생합니다. 다음과 같이

당신은 된 IQueryable의 실행을 강제 할 수

public IUser GetUser(string userName) 
{ 
    return Warehouse.GetRepository<IUser>().GetAll() 
     .AsEnumerable() 
     .First(u => u.Name == userName); 
} 

이 도메인 인터페이스가 그대로 남아있을 수 있습니다 및 중 하나를 실행할 때 어떤 문제를 포기하지 않을 것을 보장합니다.

건배!

+2

IQueryable의 지연된 실행이 문제가 아니며 (AsEnumerable()도 함께 연기했을 것입니다)하지만 실행 방법 만 수행하는 쿼리 엔진은 다릅니다. Linq2SQL은 객체 정의에 고유하지 않은 데이터베이스에 대해 계산하는 방법에 대한 정보가 필요합니다. 이것은 그 주위를 돌아 다니지 만, 전체 테이블의 많은 부분이나 심지어 전부가 요청을 위해 스캔되도록 요구합니다. –

+0

@ 조 한 한 : 맞습니다. .NET MVC를 많이 사용하기 때문에이 접근법을 사용하고 응용 프로그램 수준에서 SQL 종속성이있는 테이블을 캐시하는 것이 더 간단합니다. column 속성은이 문제를 해결하지 못합니다. 데이터베이스를 통해 생성 된 LINQ-to-SQL 클래스의 필드로 추가 매개 변수를 삽입하는 IQueryable 의 확장 기능 만 알고 있습니다. –

+0

그래서 30000 명의 사용자가 있고 일치하는 사용자가 마지막 사용자라면 사용하지 않는 데이터베이스에서 29999 명의 사용자를 검색 할 것입니까? 당신은 거의 일정한 시간 내에 검색 될 수 있도록 사용자 명에 대한 사전에 의해서조차도 메모리에 테이블을 캐싱 할 수 있지만 캐시 무효화의 모든 문제를 야기합니다. –

0

제네릭을 사용해 보셨습니까? Linq to SQL은 표현식을 SQL로 변환 할 수 있도록 구체적인 유형을 알아야합니다.

+0

우선, 응용 프로그램은 Linq2Sql 클래스에 대해 아무것도 모르기 때문에'GetRepository ()'과 같은 표현식을 볼 수는 없다 ... – ajukraine

+0

그런 다음 당신은 어떤 종류의 매핑을해야 할 것이다. Linq2Sql 유형에 응용 프로그램 클래스를 추가 할 수 있습니다. 꽤 좋지는 않지만, AutoMapper와 같은 도구를 사용하면 쉽게 작업을 수행 할 수 있습니다. – jrummell

관련 문제