2017-02-10 45 views
1

我有几类,LINQ延迟加载和创建新的对象

public class Album 
{ 
    public int AlbumId { get; set; } 
    public string Title { get; set; } 
    public Genre genre { get; set; } 
    public virtual Artist artist { get; set; } 
} 

public class Artist 
{ 
    public int ArtistId { get; set; } 
    public string Name { get; set; } 
    public virtual ICollection<Album> albums { get; set; } 
} 

public class ArtistResponse 
{ 
    public int ArtistId { get; set; } 
    public string Name { get; set; } 
} 

public class AlbumResponse 
{ 
    public int AlbumId { get; set; } 
    public string Title { get; set; } 
    public Genre genre { get; set; } 
    public ArtistResponse artist { get; set; } 
} 

我试图与艺术家下载的所有专辑,并与AlbumResponse返回。 我有一个LINQ表达

return ctx.Albums.Include(i => i.artist).Select(i => new AlbumResponse 
      { 
       AlbumId = i.AlbumId, 
       artist = new ArtistResponse { Name=i.artist.Name, ArtistId=i.artist.ArtistId}, 
       genre = i.genre, 
       Title = i.Title 
      }).ToList(); 

所以我包括“包括()”,然后创建,我创造新的ArtistResponse新AlbumResponse“艺术家”。不幸的是它不起作用。它引发一个InvalidOperationException异常。 “i.artist.ArtistId”是一个空,我不知道为什么,没有ArtistId初始化工作一切正常,只有“Name = i.artist.Name”完美地工作。

我如何附上ArtistId在“AlbumResponse”“艺术家”? 例外:“塑像,以价值型‘System.Int32’失败,因为物化值为null无论是结果型的泛型参数或查询必须使用可空类型。” 类专辑和艺术家都在数据库,ALBUMID和ArtistId是非空的。 ArtistResponse和AlbumResponse只是“额外”类添加或正从数据库信息,所以在“*回应”只是INTS

回答

3

如果artist导航属性的ArtistId列是Nullable<int>和的类型ArtistId和ALBUMID在ArtistResponse类型的ArtistId属性是int你应该检查是否有返回值:

return ctx.Albums.Include(i => i.artist).Select(i => new AlbumResponse 
{ 
    AlbumId = i.AlbumId, 
    artist = new ArtistResponse { Name = (i.artist != null) ? i.artist.Name : string.Empty, ArtistId = (i.artist != null && i.artist.ArtistId.HasValue) ? artist.ArtistId.Value : 0 }, 
    genre = i.genre, 
    Title = i.Title 
}).ToList(); 

这显然只是一个havent't发布你的类型的定义,也没有你所得到的实际的错误信息,因为你猜。

编辑:

如果你改变ArtistResponse类型的ArtistId属性的类型Nullable<int>int?):

public class ArtistResponse 
{ 
    public Nullable<int> ArtistId { get; set; } 
    public string Name { get; set; } 
} 
+0

这不起作用,它显示“HasValue”错误,“int不包含hasValue的定义...”。 – Pawel

+0

尝试使ArtistResponse类的ArtistId属性可以根据我的编辑为空。 – mm8

+0

现在有效:)但我不明白为什么......请你解释一下吗? – Pawel

1
return ctx.Albums.Include(i => i.artist).Select(i => new AlbumResponse 
      { 
       AlbumId = i.AlbumId, 
       artist = new ArtistResponse { Name=i.artist.Name, ArtistId=i.artist.ArtistId ?? 0(or Guid.NewGuid() << or this if you decide to use guid type)}, 
       genre = i.genre, 
       Title = i.Title 
      }).ToList(); 

您必须分配一个唯一的编号/您的艺术家ID的关键,如果你不想默认为零。新的GUID也许?你必须找到一种方法来创建一个独特的INT ID。

1

你可能,我不是说你没有完整的知识,没有完整的预测。实体对数据有点奇怪,因为直到它成为官方对象之前,它并没有实现。 EG:由于对象尚未实现,您的where,select和其他扩展语法无法工作。

您不妨试试作为简单的东西:

.Select(i => new AlbumResponse 
      { 
       AlbumId = i.AlbumId, 
       artist = new ArtistResponse { Name= i?.artist?.Name ?? String.Empty, ArtistId=i?.artist?.ArtistId ?? 0}, 
       genre = i.genre, 
       Title = i.Title 
      }).ToList(); 

否则投影可能无法实现它的导航属性 '艺术家')

return ctx.Albums.Include(i => i.artist) 

.ToList(。 ToList()是穷人快速实现投影的方式,本质上说:“.NET现在可以作为合法对象集合使用”。您可以使用其他我认为'First'的扩展程序。这只是一个猜测,但我知道我已经和EF一起工作了一段时间,并且在做加载事件,数学和其他事情时常常是'实现'的罪魁祸首。或者也可能像其他人所说的那样,你只是简单地得到一个对导航的空引用而已。我用一个?做了一些伪代码。条件运算符(基本上检查链中是否存在null,如果父类为null),则合并空操作符'??'说这个东西是否为null分配一个默认值。