了解实体框架下的多表结果

发布于 2024-10-08 10:07:07 字数 2649 浏览 1 评论 0原文

为了显示一个页面,我需要从各个表中获取大量信息,而目前,加载页面需要大约 20 秒,这太糟糕了。

因此,我想将所有内容移至一个存储过程中,并以旧的数据表方式获取所有信息。

我得到了这个

public WinnerPageInformation FindWinnerPageInformation(int calendarId)
{
    BackendPagesContext ctx = new BackendPagesContext(db.Connection);
    IMultipleResults results = ctx.WinnersBackendPageInformation(calendarId);

    return new WinnerPageInformation()
    {
        Challenges = results.GetResult<Challenges>(),
        Content = results.GetResult<ContentWinners>().FirstOrDefault(),
        Einfo = results.GetResult<ContentEmails>().FirstOrDefault(),
        Fields = results.GetResult<SubscriberFields>(),
        Prizes = results.GetResult<Prizes>(),
        Winners = results.GetResult<Winners>()
    };
}

, WinnersBackendPageInformation 看起来像这样

public class BackendPagesContext : DataContext
{
    public BackendPagesContext(System.Data.IDbConnection connection) 
        : base(connection) { }

    [Function(Name = "dbo.sp_GetWinnersBackendPageInformation")]
    [ResultType(typeof(JK_ContentWinners))]
    [ResultType(typeof(JK_Winners))]
    [ResultType(typeof(JK_SubscriberFields))]
    [ResultType(typeof(JK_Prizes))]
    [ResultType(typeof(JK_Challenges))]
    [ResultType(typeof(JK_ContentEmails))]
    public IMultipleResults WinnersBackendPageInformation(
        [Parameter(Name = "calendarId", DbType = "Int")] int calendarId)
    {
        IExecuteResult result =
        this.ExecuteMethodCall(this,
                               ((MethodInfo)(MethodInfo.GetCurrentMethod())),
                               calendarId);
        return (IMultipleResults)(result.ReturnValue);
    }
}

public interface IMultipleResults : IFunctionResult, IDisposable
{
    IEnumerable<TElement> GetResult<TElement>();
}

,但我面临的问题是, this.ExecuteMethodCall 行抛出一个错误,指出结果不是 MultipleTable 结果。

我的存储过程看起来像

ALTER PROCEDURE sp_GetWinnersBackendPageInformation
    @calendarId numeric = 0
AS
BEGIN 
    SELECT * FROM ContentWinners WHERE calendar_id = @calendarId;
    SELECT * FROM Winners WHERE calendar_id = @calendarId;
    SELECT * FROM SubscriberFields WHERE calendar_id = @calendarId ORDER BY position;
    SELECT * FROM Prizes WHERE calendar_id = @calendarId ORDER BY prizetype_id, to_day, title;
    SELECT * FROM Challenges WHERE calendar_id = @calendarId;
    SELECT * FROM ContentEmails WHERE calendar_id = @calendarId;
END
GO

错误消息是

为函数“WinnersBackendPageInformation”声明的多个结果类型不返回 IMultipleResults。

我缺少什么?

In order to show a page I need to grab a lot information from various tables, and for now, it takes around 20 seconds to load the page, witch is terrible.

So I want to move everything into one Store Procedure and get all that info the old DataTable way.

I get this

public WinnerPageInformation FindWinnerPageInformation(int calendarId)
{
    BackendPagesContext ctx = new BackendPagesContext(db.Connection);
    IMultipleResults results = ctx.WinnersBackendPageInformation(calendarId);

    return new WinnerPageInformation()
    {
        Challenges = results.GetResult<Challenges>(),
        Content = results.GetResult<ContentWinners>().FirstOrDefault(),
        Einfo = results.GetResult<ContentEmails>().FirstOrDefault(),
        Fields = results.GetResult<SubscriberFields>(),
        Prizes = results.GetResult<Prizes>(),
        Winners = results.GetResult<Winners>()
    };
}

and WinnersBackendPageInformation looks like this

public class BackendPagesContext : DataContext
{
    public BackendPagesContext(System.Data.IDbConnection connection) 
        : base(connection) { }

    [Function(Name = "dbo.sp_GetWinnersBackendPageInformation")]
    [ResultType(typeof(JK_ContentWinners))]
    [ResultType(typeof(JK_Winners))]
    [ResultType(typeof(JK_SubscriberFields))]
    [ResultType(typeof(JK_Prizes))]
    [ResultType(typeof(JK_Challenges))]
    [ResultType(typeof(JK_ContentEmails))]
    public IMultipleResults WinnersBackendPageInformation(
        [Parameter(Name = "calendarId", DbType = "Int")] int calendarId)
    {
        IExecuteResult result =
        this.ExecuteMethodCall(this,
                               ((MethodInfo)(MethodInfo.GetCurrentMethod())),
                               calendarId);
        return (IMultipleResults)(result.ReturnValue);
    }
}

public interface IMultipleResults : IFunctionResult, IDisposable
{
    IEnumerable<TElement> GetResult<TElement>();
}

but the problem I'm facing is that, the line this.ExecuteMethodCall throws an error saying that the result is not a MultipleTable result.

my Store Procedure looks like

ALTER PROCEDURE sp_GetWinnersBackendPageInformation
    @calendarId numeric = 0
AS
BEGIN 
    SELECT * FROM ContentWinners WHERE calendar_id = @calendarId;
    SELECT * FROM Winners WHERE calendar_id = @calendarId;
    SELECT * FROM SubscriberFields WHERE calendar_id = @calendarId ORDER BY position;
    SELECT * FROM Prizes WHERE calendar_id = @calendarId ORDER BY prizetype_id, to_day, title;
    SELECT * FROM Challenges WHERE calendar_id = @calendarId;
    SELECT * FROM ContentEmails WHERE calendar_id = @calendarId;
END
GO

Error message is

More than one result type declared for function 'WinnersBackendPageInformation' that does not return IMultipleResults.

What am I missing?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

攒眉千度 2024-10-15 10:07:07

你没有遗漏任何东西。

实体框架 4 不支持存储过程中的多个结果集。

如果您阅读博客文章 在这里,您会看到来自 EF 团队成员的以下声明:

不幸的是,这次我们无法在产品中获得对多个结果的全面支持。不过,我们确实将方法 Translate 添加到 ObjectContext,该方法允许您从 DataReader 中具体化对象。因此,如果您有一个返回多个结果的存储过程,其属性直接与 EF 对象对齐,那么您可以从上下文 (context.Connection.StoreConnection) 获取底层存储连接,创建一个命令并使用它来执行存储过程,然后取回 DataReader。然后,您可以调用 Translate 并返回这些对象的枚举,然后调用 reader.NextResult()Translate

,您可以使用一些“老式”ADO.NET,或者您可以尝试 CodePlex 似乎可以为您完成管道工作。

You're not missing anything.

Entity Framework 4 does not support multiple result sets in stored procedures.

If you read the blog post here, you'll find this statement from a member of the EF team:

Unfortunately we weren’t able to get full support for multiple results into the product this time around. We did, however, add the method Translate<T> to ObjectContext which allows you to materialize objects from a DataReader. So if you have a stored procedure which returns multiple results whose properties directly align with EF objects, then you could get the underlying store connection from the context (context.Connection.StoreConnection), create a command and use it to execute the stored procedure and get back the DataReader. Then you could call Translate<FirstObjectType> and get back an enumerable of those objects, followed by reader.NextResult() and Translate<SecondObjectType>, etc.

So, you can use some "old-school" ADO.NET, alternatively you can try the EF Extensions project on CodePlex which appears to do the plumbing for you.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文