LinqToSQl和成员访问在类型异常上不合法 [英] LinqToSQl and the Member access not legal on type exception

查看:70
本文介绍了LinqToSQl和成员访问在类型异常上不合法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

基本问题...

我有一个执行以下代码的方法:

I have a method which executes the following code:

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

GetGigs()方法通过LinqToSql从我的数据库中获取Gigs ...

The GetGigs() method gets Gigs from my database via LinqToSql...

因此,当执行GetGigs().WithArtist(artistId).ToList()时,出现以下异常:

So, when GetGigs().WithArtist(artistId).ToList() is executed I get the following exception:

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"如下所示:

Note that the extension function "WithArtist" looks like this:

    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从数据库中)构造演出集合的方法替换GetGigs()方法,则不会出现异常.

If I replace the GetGigs() method with a method that constructs a collection of gigs in code (rather than from the DB via LinqToSQL) I do NOT get the exception.

因此,我相当确定问题出在我的LinqToSQl代码而不是对象结构上.

So I'm fairly sure the problem is with my LinqToSQl code rather than the object structure.

但是,我不知道为什么LinqToSQl版本无法正常工作,因此我在下面包括了所有相关代码.非常感谢您的任何帮助!

However, I have NO IDEA why the LinqToSQl version isnt working, so I've included all the associated code below. Any help would be VERY gratefully receivced!!

LinqToSQL代码....

The LinqToSQL code....

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

我在下面包括了Act,Artist和Gig对象的代码:

I have included the code for the Act, Artist and Gig objects below:

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




}

}

推荐答案

我遇到了同样的问题,对我来说,解决这个问题的办法是分离出一个返回IQueryable<>的内联静态方法调用,以便我将其推迟存储查询一个变量并引用该变量.

I had the same issue and what seemed to do the trick for me was separating out an inline static method call that returned IQueryable<> so that I stored this deferred query into a variable and referenced that.

我认为这是Linq to SQL中的错误,但至少有一个合理的解决方法.我尚未对此进行测试,但是我的假设是,仅当在查询表达式中引用不同类的静态方法时,才可能出现此问题,而不管该函数的返回类型是否为IQueryable<>.因此,也许是持有方法的类才是问题的根源.就像我说的那样,我无法证实这一点,但可能值得调查.

I think this is a bug in Linq to SQL but at least there is a reasonable workaround. I haven't tested this out yet but my assumption is that this problem may arise only when referencing static methods of a different class within a query expression regardless of whether the return type of that function is IQueryable<>. So maybe it's the class that holds the method that is at the root of the problem. Like I said, I haven't been able to confirm this but it may be worth investigating.

更新:以防万一解决方案不清楚,我想在原始帖子的示例上下文中指出.

UPDATE: Just in case the solution isn't clear I wanted to point it out in context of the example from the original post.

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 
               }

           };
}

请注意,尽管这应该可以解决当前的问题,但似乎还存在另一个问题,因为在投影的每个元素中都访问了延迟行为查询,我想这会导致每个数据库分别向数据库发出查询在外部投影中排成一行.

Note that while this should correct the issue at hand there also seems to be another issue in that the deferred acts query is being accessed in each element of the projection which I would guess would cause separate queries to be issued to the database per row in the outer projection.

这篇关于LinqToSQl和成员访问在类型异常上不合法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆