Linq to SQL хранимые процедуры с несколькими результатами
Мы выполнили следующий подход, чтобы получить данные из нескольких результатов, используя LINQ To SQL
CREATE PROCEDURE dbo.GetPostByID
(
@PostID int
)
AS
SELECT *
FROM Posts AS p
WHERE p.PostID = @PostID
SELECT c.*
FROM Categories AS c
JOIN PostCategories AS pc
ON (pc.CategoryID = c.CategoryID)
WHERE pc.PostID = @PostID
Вызывающий метод в классе, наследуемый от DataContext, должен выглядеть так:
[Database(Name = "Blog")]
public class BlogContext : DataContext
{
...
[Function(Name = "dbo.GetPostByID")]
[ResultType(typeof(Post))]
[ResultType(typeof(Category))]
public IMultipleResults GetPostByID(int postID)
{
IExecuteResult result =
this.ExecuteMethodCall(this,
((MethodInfo)(MethodInfo.GetCurrentMethod())),
postID);
return (IMultipleResults)(result.ReturnValue);
}
}
Обратите внимание, что метод украшен не только атрибутом Function, который сопоставляется имени хранимой процедуры, но также атрибутам ReturnType с типами наборов результатов, возвращаемых хранимой процедурой. Кроме того, метод возвращает нетипизированный интерфейс IMultipleResults:
public interface IMultipleResults : IFunctionResult, IDisposable
{
IEnumerable<TElement> GetResult<TElement>();
}
чтобы программа могла использовать этот интерфейс для получения результатов:
BlogContext ctx = new BlogContext(...);
IMultipleResults results = ctx.GetPostByID(...);
IEnumerable<Post> posts = results.GetResult<Post>();
IEnumerable<Category> categories = results.GetResult<Category>();
В приведенных выше хранимых процедурах у нас было два запроса
1. Выберите запрос без присоединения
2. Выберите запрос с подключением
Но в приведенном выше втором запросе выбора данные, которые отображаются, относятся к одной из таблицы, то есть из таблицы категорий. Но мы использовали соединение и хотим отобразить таблицу данных с результатами из обеих таблиц, то есть из категорий, а также из PostCategories.
- Пожалуйста, если кто-нибудь может сообщить мне, как это сделать, используя LINQ to SQL
- Что такое компромисс производительности, если мы используем вышеуказанный подход в отношении реализации вышеуказанного подхода с помощью простого SQL
Ответы
Ответ 1
Скотт Гатри (парень, который управляет командами .Net dev в MS) рассказал, как сделать это в своем блоге несколько месяцев назад намного лучше чем когда-либо, ссылка здесь. На этой странице есть раздел под названием "Обработка нескольких форм результата из SPROC". Это объясняет, как обрабатывать несколько результатов из хранимых procs разных форм (или одинаковой формы).
Я очень рекомендую подписаться на его RSS-канал. Он в значительной степени авторитетный источник во всех вещах .Net.
Ответ 2
Хейя чувак - это работает?
IEnumerable<Post> posts;
IEnumerable<Category> categories;
using (BlogContext ctx = new BlogContext(...))
{
ctx.DeferredLoadingEnabled = false; // THIS IS IMPORTANT.
IMultipleResults results = ctx.GetPostByID(...);
posts = results.GetResult<Post>().ToList();
categories = results.GetResult<Category>().ToList();
}
// Now we need to associate each category to the post.
// ASSUMPTION: Each post has only one category (1-1 mapping).
if (posts != null)
{
foreach(var post in posts)
{
int postId = post.PostId;
post.Category = categories
.Where(p => p.PostId == postId)
.SingleOrDefault();
}
}
Ok. давайте сломаем это.
Сначала вверх, приятное соединение внутри используемого блока (так что он удаляется красиво).
Затем убедитесь, что DEFERRED LOADING выключен. В противном случае, когда u попытается выполнить и выполнить набор (например, post.Category == blah
), он увидит, что он равен нулю, lazy-load данные (например, сделать rountrip базы данных) установить данные, а THEN переопределить то, что было просто перетащено из db, с результатом метода Where(..)
. уф! Резюме: убедитесь, что отложенная загрузка отключена для области запроса.
Наконец, для каждого сообщения повторяйте и установите категорию из второго списка.
Помогает ли это?
ИЗМЕНИТЬ
Исправлено так, чтобы он не выдавал ошибку перечисления, вызывая методы ToList()
.
Ответ 3
Просто любопытно, если Post имеет один или несколько категорий, возможно ли вместо использования цикла for загружать Post.PostCategories со списком категорий (один для многих), всего одним выстрелом, используя ПРИСОЕДИНЯЙТЕСЬ?
var rslt = from p in results.GetResult<Post>()
join c in results.GetResult<Category>() on p.PostId = c.PostID
...
p.Categories.Add(c)