Вы не указываете исключение, но я предполагаю, что речь идет об оценке на стороне клиента (CSE), и вы настроили EF на выдачу исключения при его возникновении.
Это может быть First()
, который вызывает CSE, или GroupJoin
. Первый можно легко исправить с помощью FirstOrDefault()
. GroupJoin
имеет больше к этому.
Во многих случаях совсем не обязательно использовать GroupJoin
, Join
. Обычно, вручную закодированные объединения могут и должны быть заменены свойствами навигации. Это не только делает код более читабельным, но и позволяет избежать нескольких проблем, которые EF 2.x имеет с GroupJoin
.
Ваш класс SaleTable
(я не собираюсь следовать вашим именам на основе базы данных) должен иметь свойство Sales
:
public ICollection<Sale> Sales { get; set; }
А если хотите, Sale
может иметь свойство обратной навигации:
public SaleTable SaleTable { get; set; }
Настроен как
modelBuilder.Entity<SaleTable>()
.HasMany(e => e.Sales)
.WithOne(e => e.SaleTable)
.HasForeignKey(e => e.SaleTableId) // map this to ID_TABLE
.IsRequired();
Теперь использование свойства таблицы Sales
будет иметь тот же эффект, что и GroupJoin
- уникальный ключ, здесь SaleTable
, с собственной коллекцией - но без проблем.
Следующим улучшением является упрощение запроса. Двумя способами. 1. Вы неоднократно обращаетесь к первому Sale
, поэтому используйте оператор let
. 2. Запрос переведен на SQL, поэтому не беспокойтесь о пустых ссылках , но подготовьтесь к нулевым значениям . Улучшенный запрос прояснит, что я имею в виду.
var query = from st in db.SaleTables
let firstSale = st.Sales.FirstOrDefault()
select new
{
st.ID,
NrSale = (int?)firstSale.NrSale ?? 0,
IdSale = (int?)firstSale.ID ?? 0,
...
SalesSum = (int?)firstSale.SalesDetails.Sum(p => p.Price * p.Cant) ?? 0
}
Использование NrSale = firstSale.NrSale,
вызовет исключение для SaleTable
с без Sales
(объект Nullable должен иметь значение).