15

我们按照以下方法使用 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。

  1. 请如果有人可以让我知道如何使用 LINQ to SQL 来实现这一点
  2. 如果我们使用上述方法与使用简单 SQL 实现上述方法相比,性能权衡是什么
4

3 回答 3

9

Scott Guthrie(在 MS 管理 .Net 开发团队的人)几个月前在他的博客上介绍了如何做到这一点,比我以前做得更好,链接在这里。在该页面上有一个标题为“处理来自 SPROC 的多个结果形状”的部分。这解释了如何处理来自不同形状(或相同形状)的存储过程的多个结果。

我强烈建议订阅他的 RSS 提要。他几乎是.Net 上所有事物权威来源。

于 2008-12-16T14:59:06.253 回答
7

嘿,伙计——这行得通吗?

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();
    }
}

好的。让我们分解一下。

首先,在 using 块内有一个很好的连接(所以它被很好地处理掉了)。

接下来,我们确保DEFERRED LOADING 处于关闭状态。否则,当您尝试设置(例如post.Category == blah)时,它会看到它为空,延迟加载数据(例如,对数据库进行往返)设置数据,然后覆盖刚刚从数据库中拖下来的内容,与thereWhere(..)方法的结果。呸!摘要:确保在查询范围内关闭延迟加载。

最后,对于每个帖子,从第二个列表中迭代并设置类别。

这有帮助吗?

编辑

修复它,使其不会通过调用ToList()方法引发枚举错误。

于 2009-01-20T05:42:43.093 回答
0

只是好奇,如果一个帖子有一个或多个类别,是否可以使用 JOIN 一次性加载带有类别列表(一对多)的 Post.PostCategories,而不是使用 for 循环?

var rslt = from p in results.GetResult<Post>()
           join c in results.GetResult<Category>() on p.PostId = c.PostID
           ...
           p.Categories.Add(c)
于 2010-12-20T13:51:36.743 回答