Linq to SQL хранимые процедуры с несколькими результатами - PullRequest
15 голосов
/ 16 декабря 2008

Мы следовали подходу ниже, чтобы получить данные из нескольких результатов с помощью 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>();

В вышеупомянутых хранимых процедурах у нас было два запроса select 1. Выберите запрос без объединения 2. Выберите запрос с помощью Join

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

  1. Пожалуйста, если кто-нибудь может дать мне знать, как этого добиться, используя LINQ to SQL
  2. Каков компромисс производительности, если мы используем вышеупомянутый подход по отношению к реализации вышеупомянутого подхода с простым SQL

Ответы [ 3 ]

9 голосов
/ 16 декабря 2008

Скотт Гатри (парень, который руководит командами разработчиков .Net в MS) несколько месяцев назад рассказал, как сделать это в своем блоге, гораздо лучше, чем я когда-либо мог, ссылка здесь . На этой странице есть раздел под названием «Обработка нескольких форм результатов из SPROC». Это объясняет, как обрабатывать несколько результатов из сохраненных процедур разных форм (или одной формы).

Я настоятельно рекомендую подписаться на его RSS-канал. Он в значительной степени авторитетный источник по всем вопросам .Net.

7 голосов
/ 20 января 2009

Эй, чувак - это работает?

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. давайте разберемся с этим.

Во-первых, хорошее соединение внутри блока использования (поэтому оно удачно удаляется).

Далее мы убедимся, что ЗАДЕРЖКА ЗАГРУЗКИ - это off . В противном случае, когда вы попытаетесь выполнить набор (например, post.Category == blah), он увидит, что он равен нулю, отложенная загрузка данных (например, сделайте обход базы данных), установите данные, а затем переопределите то, что было просто перетащено из базы данных, с результатом использования метода Where(..). уф! Сводка: убедитесь, что отложенная загрузка отключена для объема запроса.

Последнее, для каждого поста, итерация и установка категории из второго списка.

это помогает?

EDIT

Исправлено, чтобы не вызывать ошибку перечисления при вызове методов ToList().

0 голосов
/ 20 декабря 2010

Просто любопытно, что если в Посте есть одна или несколько категорий, можно вместо использования цикла 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)
...