Есть ли способ реорганизовать linq в sql и воспользоваться преимуществами поздней оценки? Есть ли способ повторно использовать код инициализатора объекта?
У меня есть бизнес-объекты, которые хранятся в базе данных и обрабатываются отдельным слоем linq to sql.
Я хотел бы иметь возможность повторно использовать код из нескольких запросов, которые делают одно и то же. Часть запроса, которую я хотел бы использовать повторно, является частью создания объекта. Я также хотел бы продолжать использовать преимущества поздней оценки (получать только те столбцы, которые мне нужны, из базы данных).
Примеры, приведенные ниже, очень просты, и некоторые имена были изменены, чтобы защитить невинных.
Образец 1
void GetUserById(Guid userId)
{
IQueryable<LinqLayer.User> x =
from user in dataContext.Users
where user.UserID == userId
select user;
IQueryable<BusinessLayer.User> y = hydrateUser(x);
// Acutally execute the query against the database.
BusinessLayer.User user = y.First();
}
void GetUserByName(string name)
{
IQueryable<LinqUser> x =
from user in dataContext.Users
where user.FirstName == name
select user;
IQueryable<User> y = hydrateUser(x);
// Acutally execute the query against the database.
User user = y.First();
}
IQueryable<User> hydrateUser(IQueryable<LinqUser> x)
{
IQueryable<User> y;
y = from item in x
select new User
{
ID = item.UserID,
FirstName = item.FirstName,
MiddleName = item.MiddleName,
LastName = item.LastName,
};
return y;
}
В примере 1 происходит несколько вещей. В этом примере я могу воспользоваться поздней оценкой linq to sql. Если вы просматриваете запросы к базе данных, то выбираются только те столбцы, которые меня интересуют (перечислены в hydrateUser как ID, FirstName и т. Д.). Это хорошо, потому что я могу повторно использовать код в hydrateUser.
Образец 2:
IQueryable<User> hydrateUser(IQueryable<LinqUser> x)
{
IQueryable<User> y;
y = from item in x
select new User
{
ID = item.UserID,
FirstName = item.FirstName,
MiddleName = item.MiddleName,
LastName = item.LastName,
... Big long list of properties
};
return y;
}
IQueryable<User> hydrateUserWithPermissions(IQueryable<LinqUser> x)
{
IQueryable<User> y;
y = from item in x
select new User
{
ID = item.UserID,
FirstName = item.FirstName,
MiddleName = item.MiddleName,
LastName = item.LastName,
... Big long list of properties
PermissionList = item.Permissions
};
return y;
}
Образец 2 начинает падать, когда я хочу использовать hydrateUser, а также гидрировать связанный объект. Например, увлажнение списка разрешений. Теперь я должен выделить целую отдельную функцию, которая выполняет дополнительную гидратацию. это менее желательно, если у меня есть гораздо больше свойств, которые я инициализирую.
Образец 3
IQueryable<User> hydratePermissions(IQueryable<LinqUser> x)
{
IQueryable<User> y;
y = from item in x
select new User
{
PermissionList = item.Permissions
};
return y;
}
IQueryable<User> hydrateUser(IQueryable<LinqUser> x)
{
IQueryable<User> y;
y = from item in x
select new User
{
ID = item.UserID,
FirstName = item.FirstName,
MiddleName = item.MiddleName,
LastName = item.LastName,
... Big long list of properties
};
return y;
}
Что я хотел бы сделать, так это создать запрос с помощью кода, подобного примеру 3. Каким-то образом попробуйте воспользоваться обеими функциями. И совершить только одну поездку в базу данных. Однако это не работает.
Образец 4
User newUpUserFromLinqUser(LinqUser item)
{
y = new User
{
ID = item.UserID,
FirstName = item.FirstName,
MiddleName = item.MiddleName,
LastName = item.LastName,
};
return y;
}
Пример 4 близок к тому, что я хочу, но теряет оценку выражения, которую использует linq to sql для поздней оценки. Все поля вернутся в запросе. Хуже того, если подобный код является дочерним, для каждого дочернего элемента делается вызов в базу данных. В нашей ситуации это недопустимо.
Дополнительные примечания
Пропускная способность на премиум. Мы точно контролируем, какие данные поступают по проводам, поэтому очень важно, чтобы запросы были максимально точными.
Я посмотрел на LinqKit и, хотя кажется, что он может работать для того, что мне нужно, я бы предпочел "из коробки"
В настоящее время общая архитектура не подлежит обсуждению.