"UserModel.Company всегда имеет значение null."
, поскольку вы устанавливаете это с помощью выражения, которое заканчивается на .SingleOrDefault()
, я собираюсь предположить, что запрос не возвращает ни одного элемента. Начни там расследование. Если вы ожидаете ровно один элемент в u.Companies
, измените значение на .Single()
и вызовите ранний сбой.
Вы можете сделать .Single()
перед созданием нового объекта CompanyModel
, я думаю.
Что касается стиля, мне нравится синтаксис понимания запросов ("from x in y select
"), но я нахожу его неудобным в сочетании с традиционным синтаксисом точечных обозначений. Это просто трудно читать. ( LINQ - Свободное выражение и выражение запроса - есть ли одно или несколько преимуществ одного над другим? ).
Подумайте об использовании let
в понимании запроса, чтобы сделать его более понятным.
Кроме того, поскольку запрос уже возвращает IEnumerable<T>
, а вызов ToList()
заставляет все элементы быть реализованными, я бы изменил свой метод, чтобы вернуть IEnumerable<T>
, если это возможно.
Итак, в вашем случае, я бы сделал рефакторинг первым, чтобы сказать:
public IEnumerable<User> GetUsers()
{
return from u in SubsonicSqlServer.Users.All()
let c = u.Companies.Single()
select new UserModel
{
UserId = u.UserId,
Company = new CompanyModel
{
CompanyId = c.CompanyId,
CompanyName = c.CompanyName
},
FirstName = e.FirstName,
LastName = e.LastName,
BirthDate = e.BirthDate
};
}
Если это имеет смысл в вашей объектной модели, вы можете изменить User
, чтобы иметь конструктор, который принимает любой тип u
, и это становится еще проще:
return from u in SubsonicSqlServer.Users.All()
select new UserModel (u);
или даже
return SubsonicSqlServer.Users.All().Select(u => new UserModel (u));