2017-02-10 3 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(); 

Так я в том числе «художника» по «Include()», а затем создать новый AlbumResponse где я создаю новый ArtistResponse. К сожалению, это не сработает. Он выдает исключение InvalidOperationException. «i.artist.ArtistId» - это нуль, я не знаю, почему, без инициализации ArtistId все работает отлично, только с «Name = i.artist.Name» работает отлично.

Как подключить ArtistId к 'artist' в 'AlbumResponse'? Исключение: «Приведение значения к типу« System.Int32 »не выполнено, потому что материализованное значение равно нулю. Либо общий параметр результата, либо запрос должны использовать тип с нулевым значением« Классы Альбом и Исполнитель находятся в базе данных, AlbumId и ArtistId являются ненулевой. ArtistResponse и AlbumResponse просто «лишние» классы для добавления или получать информацию из базы данных, так ArtistId и ALBUMID в «* Ответ» просто INTS

ответ

3

Если ArtistId столбца artist свойства навигации является Nullable<int> и типа ArtistId свойства ArtistResponse типа 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 размещены определения ваших типов, ни фактическое сообщение об ошибке вы получаете ,

Edit:

Что делать, если вы измените тип ArtistId свойства ArtistResponse типа в Nullable<int> (int?):

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

Это не работает, оно показывает ошибку на «HasValue», «int не содержит определения для hasValue ...». – Pawel

+0

Попробуйте сделать свойство ArtistId класса ArtistResponse нулевым в соответствии с моим редактированием. – 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(); 

Вы должны присвоить уникальный номер/ключ к вашему идентификатору исполнителя, если вы не хотите, чтобы значение по умолчанию было равным нулю. возможно, новый гид? Вы должны найти способ создания уникального идентификатора int.

1

Вы можете, я не говорю, что вы делаете без полного знания, имеете неполную проекцию. Сущность немного странна в данных, поскольку она не реализована для использования вне ворот, пока она не является официальным объектом. EG: Синтаксисы синтаксиса where, select и others еще не работают, поскольку объект еще не реализован.

Вы можете попробовать что-то просто:

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

.ToList()

.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(); 

Else проекция не может быть реализована для его навигации свойства 'художник'. ToList() - это способ бедного человека быстро реализовать прогноз и, по сути, сказать: «.NET это нормально, как законная коллекция объектов». Вы можете использовать другие расширения, которые, как я полагаю, я считаю «первым».Это всего лишь предположение, но я знаю, что я некоторое время работал с EF и «осознал», когда часто случаются события загрузки, математика и другие вещи. Или это может быть так, как другие заявили, что вы просто получаете нулевую ссылку на навигацию, и она взрывается. Я сделал некоторый псевдо-код с?. условный оператор (в основном проверяет цепочку для нулей без дутья, если родитель тоже нул), то коалесцирующий нулевой оператор '??' сказать, если эта вещь равна null, присваивает значение по умолчанию.

Смежные вопросы