使用Sqlite.NET的实体框架抱怨不支持APPLY连接

时间:2016-08-26 07:41:16

标签: c# entity-framework linq sqlite

我在使用Sqlite.NET和Entity Framework执行以下连接语句时遇到问题。

我的设置是:

.NET Framework v4 Entity Framework v6.0.0.0 SQLite.EF6 v1.0.99.0 SQLite.Linq v1.0.99.0

using (var me = new ChinookContext())
{
    var screenset =
        from track in me.Tracks
        join genre in me.Genres on track.GenreId equals genre.GenreId
        join artist in me.Artists on track.Album.ArtistId equals artist.ArtistId
        into artists
        from artist in artists.DefaultIfEmpty()
        select new TrackDTO
        {
            TrackId = track.TrackId,
            TrackName = track.Name,
            GenreId = genre.GenreId,
            GenreName = genre.Name,
            ArtistId = artist.ArtistId,
            ArtistName = artist.Name
        };
        foreach (var track in screenset)
        {
            Console.WriteLine(track.TrackId + ", " + track.TrackName + ", " + track.TrackPrice);
        }
}

我得到的错误是:

  

不支持APPLY联接

这就像我可以在不经过堆栈跟踪的情况下获得内部。

数据模型基于开源的Chinook数据库。

Chinook Data model

有趣的是我在其他Sqlite.NET查询中使用了join语句,之前我没有遇到任何问题。

感谢任何帮助。

提前致谢。

更新

这是错误和堆栈跟踪:

  

准备命令定义时发生错误。有关详细信息,请参阅内部异常。不支持APPLY连接      在System.Data.Entity.Core.EntityClient.Internal.EntityCommandDefinition..ctor(DbProviderFactory storeProviderFactory,DbCommandTree commandTree,DbInterceptionContext interceptionContext,IDbDependencyResolver resolver,BridgeDataReaderFactory bridgeDataReaderFactory,ColumnMapFactory columnMapFactory)      在System.Data.Entity.Core.EntityClient.Internal.EntityProviderServices.CreateDbCommandDefinition(DbProviderManifest providerManifest,DbCommandTree commandTree,DbInterceptionContext interceptionContext)      在System.Data.Entity.Core.Objects.Internal.ObjectQueryExecutionPlanFactory.CreateCommandDefinition(ObjectContext context,DbQueryCommandTree tree)      在System.Data.Entity.Core.Objects.Internal.ObjectQueryExecutionPlanFactory.Prepare(ObjectContext context,DbQueryCommandTree tree,Type elementType,MergeOption mergeOption,Boolean streaming,Span span,IEnumerable 1 compiledQueryParameters, AliasGenerator aliasGenerator) at System.Data.Entity.Core.Objects.ELinq.ELinqQueryState.GetExecutionPlan(Nullable 1 forMergeOption)      at System.Data.Entity.Core.Objects.ObjectQuery 1.<>c__DisplayClass3.<GetResults>b__2() at System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction[T](Func 1 func,IDbExecutionStrategy executionStrategy,Boolean startLocalTransaction,Boolean releaseConnectionOnSuccess)      at System.Data.Entity.Core.Objects.ObjectQuery 1.<>c__DisplayClass3.<GetResults>b__1() at System.Data.Entity.Core.Objects.ObjectQuery 1.GetResults(Nullable 1 forMergeOption) at System.Data.Entity.Core.Objects.ObjectQuery 1..GetEnumerator&gt; b__0()      在System.Lazy 1.CreateValue() at System.Lazy 1.LazyInitValue()      在System.Data.Entity.Internal.LazyEnumerator`1.MoveNext()      在D:\ Dev \ Showcase \ ServerSqlLite \ Xxx \ Qxx.cs中的SqlLiteChinook.Qxx.SearchMusic():第36行      在D:\ Dev \ Showcase \ ServerSqlLite \ ProgramServer.cs中的SqlLiteChinook.Program.Main(String [] args):第28行

2 个答案:

答案 0 :(得分:1)

使用Lambda表达式,下面的查询将有助于提供所需的结果。

由于表之间存在良好的关系,因此您始终可以使用.Include方法,该方法将包含子表的所有行。

在下面的查询中,我完成了父表album和track之间的连接。专辑和曲目将分别包括它的儿童表艺术家和流派。

var query3 = db.Albums.Include("Artists").Join(db.Tracks.Include("Genre"), aa => aa.TrackId, tr => tr.ID, (aa, tr) => new
            {
                aa,
                tr
            }).Select(Finalrow => new TrackDTO
            {
                TrackId = Finalrow.tr.ID,
                TrackName = Finalrow.tr.Name,
                GenreId = Finalrow.tr.GENREs.Select(g => g.ID).FirstOrDefault(),
                GenreName = Finalrow.tr.GENREs.Select(g => g.Name).FirstOrDefault(),
                ArtistId = Finalrow.aa.Artists.Select(a => a.Id).FirstOrDefault(),
                ArtistName = Finalrow.aa.Artists.Select(a => a.Name).FirstOrDefault()

            }).OrderBy(t => t.TrackId);

答案 1 :(得分:0)

经过一些修改后,Nagashree的解决方案正常运行。非常感谢她。这是工作版本:

A1 = foreach A generate id,name;   
B1 = foreach B generate id,name;

M2 = union A1,B1; 
M2 = distinct M2;

M2A = JOIN M2 by id left outer,A by id;
M2AB = JOIN M2A by M2::id left outer, B by id;

Res = foreach M2AB generate M2A::M2::id as id,M2A::M2::name as name,M2A::A::age as age,B::grades as grades;

我的原始查询存在的问题是,对于var query = db.Albums.Include("Artists") .Join(db.Tracks.Include("Genre"), aa => aa.AlbumId, tr => tr.AlbumId, (aa, tr) => new { aa, tr }).Select(Finalrow => new TrackDTO { TrackId = Finalrow.tr.TrackId, TrackName = Finalrow.tr.Name, GenreId = Finalrow.tr.Genre.GenreId, GenreName = Finalrow.tr.Genre.Name, ArtistId = Finalrow.aa.ArtistId, ArtistName = Finalrow.aa.Artist.Name }).OrderBy(t => t.TrackId); Track可能为空,因此您无法访问Album。因此,Linq语句Artist将抛出异常。

对于像我这样的老式SQL编码器,这是我使用track.Album.ArtistId equals artist.ArtistId提出的工作查询:

join

这里的诀窍是加入var screenset = from track in me.Tracks join genre in me.Genres on track.GenreId equals genre.GenreId join album in me.Albums on track.AlbumId equals album.AlbumId into albums from album in albums.DefaultIfEmpty() join artist in me.Artists on album.ArtistId equals artist.ArtistId into artists from artist in artists.DefaultIfEmpty() select new TrackDTO { TrackId = track.TrackId, TrackName = track.Name, GenreId = genre.GenreId, GenreName = genre.Name, ArtistId = artist.ArtistId, ArtistName = artist.Name }; Album into并检查它是否为空。

albums

快乐的编码;)