2009-02-07 4 views
10

기본적인 문제에 불법 액세스 LinqToSQl와 회원은 ... 유형 예외

I가 다음 코드를 실행하는 방법

IList<Gig> gigs = GetGigs().WithArtist(artistId).ToList(); 

GetGigs을() 메소드 내 데이터베이스에서 연주회를 가져옵니다 LinqToSql 통해 ...

그래서, 때 GetGigs() WithArtist (ArtistID 순) .ToList() 나는 다음과 같은 예외를 얻을 실행됩니다.

Member access 'ListenTo.Shared.DO.Artist Artist' of 'ListenTo.Shared.DO.Act' not legal on type 'System.Collections.Generic.List`1[ListenTo.Shared.DO.Act] 

참고 확장 기능 "WithArtist는"이 같다고 :

public static IQueryable<Gig> WithArtist(this IQueryable<Gig> qry, Guid artistId) 
    { 
     return from gig in qry 
       where gig.Acts.Any(act => (null != act.Artist) && (act.Artist.ID == artistId)) 
       orderby gig.StartDate 
       select gig; 
    } 

나는 코드 (보다는 LinqToSQL를 통해 DB에서 공연의 컬렉션을 구성하는 방법() 메소드 GetGigs를 교체하는 경우) 나는 예외를 얻지 않는다.

그래서 개체 구조보다는 LinqToSQl 코드에 문제가 있음을 확신합니다.

그러나 LinqToSQl 버전이 작동하지 않는 이유를 알지 못하므로 아래의 모든 관련 코드를 포함 시켰습니다. 어떤 도움이라도 매우 감사하게 받아 들일 것입니다 !! 내가 법, 아티스트와 공연에 대한 코드를 포함했다

public IQueryable<ListenTo.Shared.DO.Gig> GetGigs() 
    { 
     return from g in DBContext.Gigs 
       let acts = GetActs(g.ID) 
       join venue in DBContext.Venues on g.VenueID equals venue.ID 
       select new ListenTo.Shared.DO.Gig 
       { 
        ID = g.ID, 
        Name = g.Name, 
        Acts = new List<ListenTo.Shared.DO.Act>(acts), 
        Description = g.Description, 
        StartDate = g.Date, 
        EndDate  = g.EndDate, 
        IsDeleted = g.IsDeleted, 
        Created  = g.Created, 
        TicketPrice = g.TicketPrice, 
        Venue  = new ListenTo.Shared.DO.Venue { 
            ID = venue.ID, 
            Name = venue.Name, 
            Address = venue.Address, 
            Telephone = venue.Telephone, 
            URL = venue.Website 
        } 

       }; 
    } 



    IQueryable<ListenTo.Shared.DO.Act> GetActs() 
    { 
     return from a in DBContext.Acts 

       join artist in DBContext.Artists on a.ArtistID equals artist.ID into art 
       from artist in art.DefaultIfEmpty() 

       select new ListenTo.Shared.DO.Act 
       { 
        ID = a.ID, 
        Name = a.Name, 
        Artist = artist == null ? null : new Shared.DO.Artist 
        { 
         ID = artist.ID, 
         Name = artist.Name 
        }, 
        GigId = a.GigID 

       }; 
    } 

    IQueryable<ListenTo.Shared.DO.Act> GetActs(Guid gigId) 
    { 
     return GetActs().WithGigID(gigId); 
    } 

LinqToSQL 코드는 .... 아래의 객체 :

public class Gig : BaseDO 
{ 

    #region Accessors 

    public Venue Venue 
    { 
     get; 
     set; 
    } 

    public System.Nullable<DateTime> EndDate 
    { 
     get; 
     set; 
    } 

    public DateTime StartDate 
    { 
     get; 
     set; 
    } 

    public string Name 
    { 
     get; 
     set; 
    } 

    public string Description 
    { 
     get; 
     set; 
    } 

    public string TicketPrice 
    { 
     get; 
     set; 
    } 

    /// <summary> 
    /// The Act object does not exist outside the context of the Gig, therefore, 
    /// the full act object is loaded here. 
    /// </summary> 
    public IList<Act> Acts 
    { 
     get; 
     set; 
    } 

    #endregion 
} 

public class Act : BaseDO 
{ 
    public Guid GigId { get; set; } 
    public string Name { get; set; } 
    public Artist Artist { get; set; } 
} 

public class Artist : BaseDO 
{ 
    public string Name { get; set; } 
    public string Profile { get; set; } 
    public DateTime Formed { get; set; } 
    public Style Style { get; set; } 
    public Town Town { get; set; } 
    public string OfficalWebsiteURL { get; set; } 
    public string ProfileAddress { get; set; } 
    public string Email { get; set; } 
    public ImageMetaData ProfileImage { get; set; } 

} 

public class BaseDO: IDO 
{ 
    #region Properties 

    private Guid _id; 

    #endregion 

    #region IDO Members 

    public Guid ID 
    { 
     get 
     { 
      return this._id; 
     } 
     set 
     { 
      this._id = value; 
     } 
    } 




} 

}

+0

나는이 같은 오류로 실행하고 내 경우에는 내 WHERE 절 내에서 상관 하위 쿼리의 사용과 관련된 것으로 보인다. 정보를 찾으면 업데이트를 드리겠습니다. – jpierson

답변

1

내가 볼 수 없습니다 LINQ to SQL이 어느 열이 어느 컬럼인지 알아내는 방법을 나타내는 클래스의 항목.

W 당신은 WithArtist 메소드가 .NET에서 실행되거나 SQL로 변환 될 것이라고 기대합니까? SQL로 변환 될 것으로 예상되는 경우 적절한 LINQ to SQL 특성을 사용하여 Gig 클래스를 꾸미거나 데이터 컨텍스트를 다른 방식으로 구성해야합니다. 코드에서 실행하려면 첫 번째 매개 변수 유형을 IQueryable<Gig>에서 IEnumerable<Gig>으로 변경하십시오.

+0

자동 생성 된 LinqToSQl gig 클래스가 있습니다. 위에 정의 된 gig 클래스는 LinqToSQl 데이터를 ...로 변환하는 스키마 구동 객체입니다. – iasksillyquestions

+0

그래서 GetGigs()에서 리턴하는 Gig 유형은 LINQ to SQL에 대해 알고 있습니다. –

+0

@ 존 : 당신이 바쁘다는 것을 알고 있습니다. (그리고이 질문은 오랜 옛날 일입니다.) 그러나 SQL *로 변환 될 *에 중점을 둔 몇 가지 코드로 답을 자세히 설명 할 수있는 기회가 있습니다. 각도. 나는 똑같은 문제를 여기에서 가지고있다. (예 : GetActs()) + 파이프 및 필터 (예 : 아티스트())와 리포지토리 패턴이 다른 * children * 속성 (예 : Gigs는 부모, Acts 속성은 자식)을 처리하지 않습니다. , 그래서 소비자 코드가있는 경우, Assosiated 자식을 동적으로 반환하는 쿼리 (예 : WithActs())를 조작하려고했습니다. 이 문제는 나를 죽이고 있습니다. ( –

4

문제는 GetGigs에서 'let'문이라고 생각합니다. 'let'을 사용한다는 것은 가져올 기본 세트와 별도로 최종 쿼리의 일부를 정의한다는 것을 의미합니다. 문제는 'let'이 스칼라가 아닌 경우 중첩 된 쿼리가 발생한다는 것입니다. 중첩 된 쿼리는 실제로 Linq가 SQL의 가장 강력한 포인트가 아니기 때문에 지연 실행됩니다. 쿼리에서 중첩 쿼리의 결과를 반환 할 기본 집합의 투영에 배치 한 다음 linq 연산자를 추가로 추가합니다.

이렇게되면 중첩 된 쿼리가 실행될 쿼리에 더 깊숙이 묻혀서 중첩 된 쿼리가 실행할 쿼리의 외부 투영에 있지 않으므로 병합해야합니다. SQL 쿼리에 DB를 실행. 이것은 기본 SQL 쿼리 내에 중첩 된 투영에서 중첩 된 쿼리이고 SQL에 투영 안에 중첩 된 쿼리를 가져올 수 없으므로 SQL에 '투영 된 중첩 쿼리'와 같은 개념이 없습니다. SQL, 스칼라 만.

+0

그럼 let을 사용하지 않고 액트 컬렉션을로드하려면 어떻게해야합니까? – iasksillyquestions

+0

많은 도움을 주셔서 감사합니다 !! – iasksillyquestions

+0

이 방법을 사용하면되지만 쿼리 연산자를 쿼리에 추가 할 수 없습니다. 중첩 쿼리는 외부 투영에 있어야합니다. 따라서 GetGigs 자체의 쿼리는 중첩 쿼리와 함께 실행됩니다. –

5

나는 동일한 문제가 있었는데, 나를 위해 속임수를 쓰는 것처럼 보였던 것은 IQueryable <을 반환하는 인라인 정적 메서드 호출을 분리하여이 지연된 쿼리를 변수에 저장하고이를 참조했습니다.

나는 이것이 Linq에서 SQL 로의 버그라고 생각하지만 합리적인 해결책이 적어도있다. 아직 테스트하지는 않았지만 내 가정은이 함수의 반환 형식이 IQueryable <>인지 여부에 관계없이 쿼리 식 내에서 다른 클래스의 정적 메서드를 참조 할 때만이 문제가 발생할 수 있다는 것입니다. 어쩌면 문제의 근원에있는 메소드를 보유하고있는 클래스 일 수 있습니다. 내가 말했듯이, 나는 이것을 확인할 수 없었지만 조사 할 가치가있을 수 있습니다.

업데이트 : 해결책이 명확하지 않은 경우 원래 게시물의 예와 관련하여 지적하고 싶습니다. 이 손의 문제를 해결해야하는 동안 것을

public IQueryable<ListenTo.Shared.DO.Gig> GetGigs() 
{ 
    var acts = GetActs(g.ID); // Don't worry this call is deferred 

    return from g in DBContext.Gigs 
      join venue in DBContext.Venues on g.VenueID equals venue.ID 
      select new ListenTo.Shared.DO.Gig 
      { 
       ID = g.ID, 
       Name = g.Name, 
       Acts = new List<ListenTo.Shared.DO.Act>(acts), 
       Description = g.Description, 
       StartDate = g.Date, 
       EndDate  = g.EndDate, 
       IsDeleted = g.IsDeleted, 
       Created  = g.Created, 
       TicketPrice = g.TicketPrice, 
       Venue  = new ListenTo.Shared.DO.Venue { 
           ID = venue.ID, 
           Name = venue.Name, 
           Address = venue.Address, 
           Telephone = venue.Telephone, 
           URL = venue.Website 
       } 

      }; 
} 

참고가도 발행 할 내가 별도의 쿼리를 야기 거라 생각 투사의 각 요소에 액세스하는 것을 지연 행위 쿼리에 또 다른 문제가 될 것 같다 외부 프로젝션의 행당 데이터베이스에 저장됩니다.

+1

대단히 고맙습니다. 동일한 문제가 있었고 변수에 넣으면 실제로 문제가 해결됩니다. 그리고 나는 Linq에서 SQL에 이르는 버그와 같은 느낌이 든다고 동의한다. – Magnus

+1

디버깅하는 동안 내 확장 프로그램에서 중단 점을 설정하고 충돌이 발생하지 않았습니다. 내 쿼리의 확장 메서드 부분에 대한 변수를 만든 후 모든 것이 작동하고 중단 점이 발생했습니다. –

+3

방금이 문제에 부딪 혔고 google을 통해 내 자신의 제안 된 솔루션을 찾았습니다. 문제가 다시 해결되었습니다. StackOverflow에서 처음 해보았다고 말할 수 있었으면 좋겠습니다. – jpierson

관련 문제