2013-04-06 4 views
2

Мне нужен этот запрос linq для работы, но linq жалуется на то, что clientcontact и телефон являются int64, и мне также нужно выполнить второй столбец, но я боюсь, что это не работает по той же причине. Если я добавлю tostring(), это просто говорит, что linq не распознает его.LINQ cast int64 issue

база {System.SystemException} = { "Невозможно бросить тип 'System.Int64' к типу 'System.Object'. LINQ к Entities поддерживает только литья EDM примитивные или перечисления типов."}

var tempCustomers = 
        from c in db.Customers 
        let cc = db.CustomerContacts.FirstOrDefault(x => x.CustomerID == c.CustomerID) 
        select new{cc.CustomerContactID, CustomerValue = c.CustomerName + " 	 	 " + cc.Phone}; 
+0

Возможно, попробуйте 'cc.Phone.ToString()'? –

+0

base {System.SystemException} = {«LINQ to Entities не распознает метод« Система ».String ToString() ', и этот метод не может быть переведен в выражение хранилища. "} – Preston

+3

Почему нет cc.Phone строки? Это, конечно, не int64 .... [Какой правильный способ представления телефона номера?] (http://stackoverflow.com/a/3483166/1808494) – Aron

ответ

1

Эта ошибка исходит от LINQ к объектам. Вот одно из решений:

var tempCustomers = 
    from c in db.Customers.ToArray() 
    let cc = db.CustomerContacts 
     .FirstOrDefault(x => x.CustomerID == c.CustomerID) 
    select new 
    { 
     cc.CustomerContactID, 
     CustomerValue = string.Format("{0} 	 	 {0}", 
      c.CustomerName, cc.Phone) 
    }; 

Вышеупомянутое попадет в базу данных, прежде чем попытается выполнить конкатенацию строк. Если это неприемлемо, обратите внимание на этот вопрос.

Почему это не работает

LINQ для лиц использует отложенное выполнение SQL, а это означает, что ваш запрос LINQ не попал в базе данных, пока не перебрать IQueryable с использованием Еогеаспа, или вызвать метод, как ToList или ToArray на IQueryable. Вы можете использовать любой код в выражении предиката LINQ, но он не будет работать во время выполнения, если LINQ to Entities не сможет понять, как его перевести в SQL. Ваш код не работает, поскольку LINQ to Entities не может понять, как конкатенация CustomerName, вашей пользовательской строки и PhoneNumber во время выполнения SQL-запроса. Вышеупомянутое работает, потому что оно сначала получает данные из базы данных, а затем конкатенация строк в памяти.

Update

Чтобы расширить на лучшее решение, которое @JeffMercado бить меня, вы действительно должны использовать свойство навигации, чтобы присоединиться к Customer и CustomerContacts. Это устранит необходимость в пункте let и First или FirstOrDefault вызов:

public class Customer 
{ 
    public long CustomerID { get; set; } 
    public string CustomerName { get; set; } 
    public virtual ICollection<CustomerContact> Contacts { get; set; } 
} 

public class CustomerContact 
{ 
    public long CustomerContactID { get; set; } 
    public long CustomerID { get; set; } 
    public virtual Customer Owner { get; set; } 
    public long Phone { get; set; } // I agree this should be a string 
} 

Затем вы должны иметь возможность запрашивать из данных, как это:

var query = db.CustomerContacts 
    .Include(x => x.Owner) // eager load to avoid multiple separate SQL queries 
    .Select(x => new { 
     CustomerContactID = x.CustomerContactID, 
     CustomerName = x.Owner.CustomerName, 
     Phone = x.Phone, 
}); 

здесь, вы можете использовать AsEnumerable, ToArray, или ToList, чтобы выполнить запрос и отформатировать ваше специальное свойство CustomerValue.

var results = query 
    .ToArray() // or .AsEnumerable(), or .ToList(), all will execute the SQL query 
    .Select(x => new { 
     CustomerContactId = x.CustomerContactID, 
     CustomerValue = string.Format("{0} &#09;&emsp;&#09; {1}", 
      x.CustomerName, x.Phone) 
}); 
0

Виды операций, которые вы можете выполнять в запросе, ограничены в EF, конверсии являются одним из них. Вам нужно перенести эту часть из запроса, просто получая данные, затем используйте AsEnumerable(), чтобы вы работали с LINQ to Objects. Затем вы можете делать все, что хотите, с данными.

var query= 
    from c in db.Customers 
    let cc = c.CustomerContacts.FirstOrDefault() // better to use the navigation properties instead 
    select new // select the fields you need 
    { 
     cc.CustomerContactId, 
     c.CustomerName, 
     Phone = (long?)cc.Phone, // cc could potentially be null this long must also be nullable 
    }; 
var tempCustomers = 
    from x in query.AsEnumerable() // LINQ to Objects 
    select new // now you can do what you want to the data 
    { 
     x.CustomerContactId, 
     CustomerValue = x.CustomerName + " &#09;&emsp;&#09; " + x.Phone, 
    }; 

Я ворвался в отдельные заявления для удобства чтения, но вы можете комбинировать их, если хотите.

+0

Когда я отлаживаю и пытаюсь развернуть результаты запроса var, все, что я получаю, это base {System.SystemException} = {"Неверное значение для значения типа Int64, потому что материализованное значение равно нулю. Либо общий параметр результата, либо запрос должен использовать тип с нулевым значением. "} – Preston

+0

Вам нужно иметь в виду, что с помощью' FirstOrDefault() ',' cc' потенциально может быть «null», поэтому в действительности все типы значений, которые вы хотите выбрать, должны быть объявлены нулевыми. –

+0

Насколько мне жаль, в этом не было проблемы, я просто дважды проверял, что они не имеют нулевых значений в обоих местах, и нет записей в БД без телефона. – Preston