2009-02-07 27 views
10

Vấn đề cơ bản ...linqtosql và thành viên truy cập không hợp pháp vào loại ngoại lệ

Tôi có một phương pháp mà thực thi đoạn mã sau:

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

Các GetGigs() phương pháp được hợp đồng biểu diễn từ cơ sở dữ liệu của tôi qua LinqToSql ...

Vì vậy, khi GetGigs() WithArtist (artistId) ToList() được thực hiện tôi nhận được ngoại lệ sau đây:.

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] 

Lưu ý rằng các chức năng mở rộng "WithArtist" trông như thế này:

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; 
    } 

Nếu tôi thay thế GetGigs phương pháp() với một phương pháp mà xây dựng một tập hợp các hợp đồng biểu diễn trong đang (chứ không phải từ DB qua LinqToSQL) Tôi KHÔNG nhận được ngoại lệ.

Vì vậy, tôi khá chắc chắn vấn đề là với mã LinqToSQl của tôi chứ không phải là cấu trúc đối tượng.

Tuy nhiên, tôi KHÔNG có IDEA lý do tại sao phiên bản LinqToSQl không hoạt động, vì vậy tôi đã bao gồm tất cả mã được liên kết bên dưới. Bất kỳ sự trợ giúp nào cũng sẽ được VERY biết ơn!

Mã 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); 
    } 

Tôi đã bao gồm mã cho Đạo luật, Artist và Gig các đối tượng dưới đây:

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

Tôi đang chạy vào cùng một lỗi này và trong trường hợp của tôi, dường như có liên quan đến việc sử dụng truy vấn con tương quan trong mệnh đề WHERE của tôi. Nếu tôi tìm thấy bất kỳ thông tin nào tôi sẽ cung cấp cho bạn một bản cập nhật. – jpierson

Trả lời

1

Tôi không thấy bất cứ điều gì trong lớp học của bạn để chỉ ra cách LINQ to SQL có nghĩa là làm việc ra cột nào, v.v.

W Bạn có mong đợi phương thức WithArtist được thực hiện trong .NET hay được chuyển đổi thành SQL không? Nếu bạn mong đợi nó được chuyển đổi thành SQL, bạn sẽ cần phải trang trí lớp Gig của bạn với các thuộc tính LINQ to SQL thích hợp (hoặc cấu hình ngữ cảnh dữ liệu của bạn theo một cách khác). Nếu bạn muốn nó được thực hiện trong mã, chỉ cần thay đổi kiểu tham số đầu tiên từ IQueryable<Gig> thành IEnumerable<Gig>.

+0

Có các lớp biểu diễn LinqToSQl được tạo tự động. Lớp biểu diễn được định nghĩa ở trên là các đối tượng được định hướng lược đồ mà tôi đang thích ứng với Dữ liệu LinqToSQl vào ... – iasksillyquestions

+0

Vì vậy, loại Gig bạn đang quay trở lại từ GetGigs() mà LINQ to SQL biết hay không? –

+0

@Jon: Tôi biết bạn đang bận (và câu hỏi này khá cũ, bây giờ), nhưng có bất kỳ cơ hội nào bạn có thể xây dựng trên câu trả lời của bạn với một số mã .. với sự nhấn mạnh vào * để được chuyển đổi sang SQL *, góc. Tôi có cùng một vấn đề ở đây. Tôi đang sử dụng mẫu Repository (ví dụ GetActs()) + Pipes and Filters (ví dụ: Với Artist()) và kho lưu trữ của tôi không xử lý các thuộc tính * children * khác (ví dụ: Gigs là parent, Acts property là child) , vì vậy tôi đã cố gắng thao tác truy vấn (ví dụ: WithActs()) để tự động trả lại một đứa trẻ bị tấn công, nếu mã người tiêu dùng cho điều đó. Vấn đề này đang giết chết tôi: ( –

4

Tôi nghĩ vấn đề là tuyên bố 'let' trong GetGigs. Sử dụng 'let' có nghĩa là bạn xác định một phần của truy vấn cuối cùng tách biệt với tập hợp chính để tìm nạp. vấn đề là 'let', nếu nó không phải là một vô hướng, dẫn đến một truy vấn lồng nhau. Các truy vấn lồng nhau không thực sự là LINQ đối với điểm mạnh nhất của sql khi chúng được thực thi cũng được hoãn lại. Trong truy vấn của bạn, bạn đặt kết quả của truy vấn lồng nhau vào phép chiếu của tập hợp chính để trả về mà sau đó được nối thêm với các toán tử LINQ.

Khi điều đó xảy ra, truy vấn lồng nhau được chôn sâu hơn vào truy vấn sẽ được thực hiện và điều này dẫn đến một trường hợp truy vấn lồng nhau không nằm trong chiếu ngoài của truy vấn để thực thi và do đó phải được hợp nhất vào truy vấn SQL chạy trên DB. Đây không phải là doable, vì nó là một truy vấn lồng nhau trong một phép chiếu lồng nhau trong truy vấn sql chính và SQL không có khái niệm như 'truy vấn lồng nhau trong một phép chiếu', vì bạn không thể tìm nạp một tập hợp các phần tử bên trong một phép chiếu trong SQL, chỉ có vô hướng.

+0

Vậy làm cách nào để tải một bộ sưu tập các hành vi mà không cần sử dụng? – iasksillyquestions

+0

Cảm ơn rất nhiều vì đã giúp bạn !! – iasksillyquestions

+0

Bạn có thể sử dụng nó theo cách bạn làm, nhưng sau đó bạn không thể nối thêm toán tử truy vấn vào truy vấn đó: truy vấn lồng nhau phải nằm trên chiếu ngoài. Vì vậy, truy vấn của GetGigs sẽ chạy với truy vấn lồng nhau. –

5

Tôi đã gặp vấn đề tương tự và những gì dường như làm thủ thuật cho tôi đã tách ra một cuộc gọi phương thức tĩnh nội dòng trả lại IQueryable <> để tôi lưu trữ truy vấn bị trì hoãn này thành một biến và tham chiếu điều đó.

Tôi nghĩ đây là lỗi trong LINQ to SQL nhưng ít nhất cũng có giải pháp hợp lý. Tôi chưa thử nghiệm điều này nhưng giả định của tôi là vấn đề này có thể phát sinh chỉ khi tham chiếu các phương thức tĩnh của một lớp khác trong một biểu thức truy vấn bất kể kiểu trả về của hàm đó là IQueryable <>. Vì vậy, có lẽ đó là lớp học giữ phương pháp đó là gốc của vấn đề. Như tôi đã nói, tôi đã không thể xác nhận điều này nhưng nó có thể đáng để điều tra.

CẬP NHẬT: Chỉ trong trường hợp giải pháp không rõ ràng, tôi muốn chỉ ra nó trong ngữ cảnh ví dụ từ bài đăng gốc.

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 
       } 

      }; 
} 

Lưu ý rằng mặc dù điều này sẽ khắc phục vấn đề ở đó cũng có vẻ là một vấn đề khác trong truy vấn hành vi trì hoãn đang được truy cập trong từng phần tử chiếu mà tôi đoán sẽ tạo ra các truy vấn riêng biệt vào cơ sở dữ liệu trên mỗi hàng trong phép chiếu ngoài.

+1

Cảm ơn bạn rất nhiều, đã có cùng một vấn đề và đặt nó vào một biến thực sự giải quyết vấn đề. Và tôi đồng ý, nó giống như một lỗi trong LINQ to SQL. – Magnus

+1

Tôi đặt điểm ngắt trong các phương thức tiện ích mở rộng của mình trong khi gỡ lỗi này và thậm chí chúng không bị ảnh hưởng. Sau khi tạo một biến cho phần phương thức mở rộng của truy vấn của tôi, mọi thứ đã hoạt động và các điểm ngắt được nhấn. –

+3

Tôi chỉ gặp vấn đề này và tìm thấy giải pháp được đề xuất của riêng tôi qua google, một lần nữa giải quyết được vấn đề tôi gặp phải. Tôi ước tôi có thể nói đây là lần đầu tiên tôi làm điều đó trên StackOverflow. – jpierson

Các vấn đề liên quan