【问题标题】:Silverlight RIA DomainService with 2 million rows in a tableSilverlight RIA DomainService,表中有 200 万行
【发布时间】:2011-08-23 13:20:00
【问题描述】:

我正在做一个从 oracle 数据库读取的项目。我使用了 Silverlight RIA 和自动生成的 DomainService,因为我不太关心结构化,因为我只担心显示数据。

我的问题是,当我使用 XAML 中的 domaindatasource 并使用 fiddler 调试 WCF 服务及其调用时,useraccounts 表中的第一组数据包含 200 万行,并且 DomainService 超时。

现在我尝试将服务的超时时间增加到 20 分钟,但仍然无济于事,我收到错误消息:

查询“GETUA_USERACCOUNTS”的加载操作失败。 http 请求已超过分配的超时时间

在我使用的总共 9 个表中,3 个表有大约 200 万行,解决这个问题的最佳方法是什么?

【问题讨论】:

  • 客户端应用永远不需要全部 200 万条记录。您是否在数据显示中添加了分页/过滤?
  • 您好,谢谢您,我忘了说我不必显示所有数据,我需要在客户端找到当前记录。一个用户输入一个用户ID,然后我从各个表中提取有关该用户ID的所有信息,3个表有200万行,所以这会导致超时。
  • 如果您要立即过滤这些数据,需要将大量数据发送到 Silverlight 客户端应用程序。这听起来像是您想要在服务器端执行的操作,即使它需要 Silverlight 和您的服务端点之间的多个请求。
  • 谢谢 avanek,我会按照你说的那样尝试,我可以遵循任何最佳实践或示例来实现这一目标?
  • 我对 RIA 不太熟悉(我曾参与过一个只有 Silverlight + WCF 的项目),但在大多数情况下,我发现使用 Repository software pattern 有助于解决此类问题问题。在 WCF 层中创建一个 Getter 方法,该方法接受 UserID 并将返回单个记录而不是整个数据集。

标签: c# silverlight wcf ria domainservices


【解决方案1】:

使用 ToTraceString 方法...

http://msdn.microsoft.com/en-us/library/system.data.objects.objectquery.totracestring.aspx

...或 Oracle 分析工具来确定正在使用的 SQL 语句并确认它需要很长时间才能执行。

使用查询优化技术,例如添加索引来加快速度。

或者,编写一个以更有效的方式返回所需结果的存储过程。

【讨论】:

  • 感谢 Scott 的帮助,我会按照您的建议进行尝试,并会尽快回复您。
【解决方案2】:

要从 TomTom 停止的地方继续,Red 询问,请在服务器上进行数据过滤/处理,然后返回结果(伪代码)

public IQueriable<UserDTO> GetUserAccountDetails(string UserID)
{
    DataSet oneBazillionRows = SQLServer.GetAllUserRows();

    // LINQ to the rescue
    return from user in oneBillionRows
           where user.ID = UserID;
}

和您的消费者:

public void GetUserInfo()
{
    ServiceContext context = new ServiceContext();
    context.Load<UserDTO>(ServiceContext.GetUserAccountDetailsQuery(), load =>
    {
        // do some work here
        //like signalling the call is complete
        // or storing the data in your View Model
    }, null);
}

您的消费者将只收到一个数据行。基本形式是这样的:

public IQueriable<ReturnType> WebService(Parameter parameter, ...)
{
    // Do all your work here, return minimal results
}

请考虑:服务器总是比您的客户端机器强大得多。让它完成过滤/排序/预处理结果的所有工作,并让它交出最少的数据。您会发现您的 RIA 实现变得更加灵活。

【讨论】:

  • 感谢您的帮助,我会按照您的建议尝试。干杯
【解决方案3】:

您应该使用 DataPager,请参见此处:http://www.silverlightshow.net/items/Creating-applications-with-.NET-RIA-Services-Part-4-Adding-a-DomainDataSource.aspx

<navigation:Page x:Class="WebAdministrationTool.ManageUsers" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:ria="clr-namespace:System.Windows.Controls;assembly=System.Windows.Ria.Controls"
    xmlns:local="..."
    xmlns:validation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.DataForm">

    <Grid x:Name="LayoutRoot">

        <data:DataGrid x:Name="UsersGrid" 
                       IsReadOnly="True" 
                       AutoGenerateColumns="True"
                       ItemsSource="{Binding Data, ElementName=MyDataSource}" />

        <validation:DataPager x:Name="UsersPager"
                              PageSize="10" 
                              Source="{Binding Data, ElementName=MyDataSource}" />

        <ria:DomainDataSource x:Name="MyDataSource" LoadMethodName="LoadHugeAmountOfRows">
            <ria:DomainDataSource.DomainContext>
                <local:MyDomainContext />
            </ria:DomainDataSource.DomainContext>
        </ria:DomainDataSource>

    </Grid>

</navigation:Page>

【讨论】:

  • 感谢您的回复,我实际上并没有显示所有数据,我必须从表中所有200万条记录的实际列表中找到当前记录。我将如何进行?
  • 您应该将 FilterDescriptor 添加到 DomainDataSource。在此处查看示例实现:msdn.microsoft.com/en-us/library/…
  • 再次感谢 DenisPostu,但我想我应该对这个问题更清楚。这是我遇到的情况。我忘了提到我不必显示所有数据,我需要在客户端找到当前记录。一个用户输入一个用户ID,然后我从各个表中提取有关该用户ID的所有信息,3个表有200万行,所以这导致超时
  • 如果你不想显示数据,不要拉它。就这么简单。这不是 RIA 问题,这是 20 年的设计实践。放入过滤器。仅获取您打算显示的数据。就这么简单。
  • 感谢 TomTom,所以当用户输入用户 ID 时,为了让我从表中获取用户的详细信息,我必须遍历行以找出客户端上的所有信息或在服务器端?所以我该怎么做,请指导我,因为我是一名学生,并且愿意学习
【解决方案4】:

我遇到了类似的问题,为了解决这个问题,我在我的数据库上创建了存储过程来完成这项工作,并且只返回我需要的信息。没有太多关于将存储过程添加到 RIA 的信息,但这里是我所知道的工作的一个镜头。

  1. 创建您的存储过程
  2. 更新项目中的数据库模型以包含存储过程
  3. 在模型浏览器中右键单击并添加功能导入。在这里,您可以命名并决定如何返回数据(让您自己轻松并尝试返回您的 DomainService.metadata.cs 文件中已有的对象)
  4. 如果创建新的返回对象,请将其添加到您的 DomainService.metadata.cs 文件中
  5. 在您的域服务中添加一个返回结果列表的公共方法。

    public IQueryable<FWCUser> UpdateFWCUserWithUserProfileID(int userProfileID, int fwcUserID)
    {
       return this.ObjectContext.UpdateFWCUserWithUserProfileID(userProfileID, fwcUserID).AsQueryable();
    }
    
  6. 构建您的项目并根据需要从后面的代码中调用方法

    FWCDomainContext context = new FWCDomainContext();
    context.Load(context.UpdateFWCUserWithUserProfileIDQuery(num1, num2), Completed, null);
    

【讨论】:

  • 感谢您的帮助,非常感谢。干杯
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-11
  • 1970-01-01
相关资源
最近更新 更多