ADO.NET (WCF) 数据服务查询拦截器挂起 IIS

发布于 2024-08-26 23:30:11 字数 3327 浏览 9 评论 0原文

我有一个 ADO.NET 数据服务,它应该提供对稍微复杂的数据库的只读访问。

从逻辑上讲,我的数据模型中有每个类型表 (TPT) 继承,但 EDM 没有实现继承。 (派生类型上数据服务和导航属性的限制。.NET 4 中仍未修复!)我可以使用我尝试针对 Web 服务运行的查询副本直接查询我的 EDM(使用单独的项目), 10秒内返回结果。禁用查询拦截器后,我可以对 Web 服务进行相同的查询,结果也同样快速返回。我可以启用一些查询拦截器,并且结果会缓慢返回,最多一分钟左右。或者,我可以启用所有查询拦截器,在我正在查询的主对象上扩展较少的属性,并在相似的时间内返回结果。 (我增加了一些超时期限)

到目前为止,Sql Profiler 表明速度变慢的是数据库。 (那是另一天的帖子)但是当我启用所有查询拦截器并展开所有属性时,我希望 IIS 工作进程将 CPU 固定 20 分钟,并且甚至不会对数据库进行查询,即查询永远不会通过网络服务器。这对我来说意味着,是的,我的实现可能很糟糕,但无论数据服务“层”是否存在问题,它都不应该出现问题。对于我未经训练的眼睛来说,WCF 跟踪没有显示任何有趣的内容。

详细信息:

  • 数据模型:代理 -> 个人 -> 学生
  • 学生有推荐的集合
  • 学生和推荐是私有的,针对网络服务的查询应该只返回“您的”学生和推荐。这意味着 Person 和 Agent 也需要被过滤。其他实体(代理->组织->学校)可以由经过身份验证的任何人访问。
  • 现有的安全模型不太适合对此类数据访问执行此类过滤,查询拦截器很复杂并导致 EF 生成一些有趣 sql 查询。

示例拦截器

[QueryInterceptor("Agents")]
    public Expression<Func<Agent, Boolean>> OnQueryAgents()
    {
        //Agent is a Person(1), Educator(2), Student(3), or Other Person(13); allow if scope permissions exist
    return ag =>
               (ag.AgentType.AgentTypeId == 1 || ag.AgentType.AgentTypeId == 2 || ag.AgentType.AgentTypeId == 3 || ag.AgentType.AgentTypeId == 13) &&                
            ag.Person.OrganizationPersons.Count<OrganizationPerson>(op =>
                op.Organization.ScopePermissions.Any<ScopePermission>
                    (p => p.ApplicationRoleAccount.Account.UserName == HttpContext.Current.User.Identity.Name && p.ApplicationRoleAccount.Application.ApplicationId == 124) ||
                op.Organization.HierarchyDescendents.Any<OrganizationsHierarchy>(oh => oh.AncestorOrganization.ScopePermissions.Any<ScopePermission>
                    (p => p.ApplicationRoleAccount.Account.UserName == HttpContext.Current.User.Identity.Name && p.ApplicationRoleAccount.Application.ApplicationId == 124))) > 0; 
    }

Person、Student、Referral 的查询拦截器都非常相似,即它们遍历多个相同/相似的表来查找上述 ScopePermissions。

示例查询

此示例查询只是一个示例,旨在向第三方说明如何使用所提供的 Web 服务访问数据。我意识到生产查询不会有那么多扩展。 (但还要记住,要获得 OOP 意义上的整个对象,我需要一个 Agent、Person 和 Student 行。)

var referrals =
            (from r in service.Referrals
                 .Expand("Organization/ParentOrganization")              
                 .Expand("Educator/Person/Agent")
                 .Expand("Student/Person/Agent")
                 .Expand("Student")
                 .Expand("Grade")
                 .Expand("ProblemBehavior")
                 .Expand("Location")
                 .Expand("Motivation")
                 .Expand("AdminDecision")
                 .Expand("OthersInvolved")
             where
                 r.DateCreated >= coupledays &&
                 r.DateDeleted == null
             select r);

任何建议或提示都将与修复我当前的实现或开发新的实现密切相关,但需要注意的是现有的数据库逻辑无法更改(尽管我可以添加),并且最终我需要通过 Web 服务公开数据库的大部分内容,该服务限制对授权数据的数据访问,以实现数据集成与多个外部团体。这些外部各方将定期执行批处理作业,将我们的数据导入他们的数据库/数据仓库。

谢谢你!!!

更新:在 MSDN 上发布了此问题,收到了类似的反馈。 http://social .msdn.microsoft.com/Forums/en-US/adodotnetdataservices/thread/1ccfc96c-dd35-4879-b36b-57e915d5e02f/

I have an ADO.NET Data Service that's supposed to provide read-only access to a somewhat complex database.

Logically I have table-per-type (TPT) inheritance in my data model but the EDM doesn't implement inheritance. (Limitation of Data Services and navigation properties on derived types. STILL not fixed in .NET 4!) I can query my EDM directly (using a separate project) using a copy of the query I'm trying to run against the web service, results are returned within 10 seconds. Disabling the query interceptors I'm able to make the same query against the web service, results are returned similarly quickly. I can enable some of the query interceptors and the results are returned slowly, up to a minute or so later. Alternatively, I can enable all the query interceptors, expand less of the properties on the main object I'm querying, and results are returned in a similar period of time. (I've increased some of the timeout periods)

Up til this point Sql Profiler indicates the slow-down is the database. (That's a post for a different day) But when I enable all my query interceptors and expand all the properties I'd like to have the IIS worker process pegs the CPU for 20 minutes and a query is never even made against the database, ie the query never makes it past the web server. This implies to me that yes, my implementation probably sucks but regardless the Data Services "tier" is having an issue it shouldn't. WCF tracing didn't reveal anything interesting to my untrained eye.

Details:

  • Data model: Agent->Person->Student
  • Student has a collection of referrals
  • Students and referrals are private, queries against the web service should only return "your" students and referrals. This means Person and Agent need to be filtered too. Other entities (Agent->Organization->School) can be accessed by anyone who has authenticated.
  • The existing security model is poorly suited to perform this type of filtering for this type of data access, the query interceptors are complicated and cause EF to generate some entertaining sql queries.

Sample Interceptor

[QueryInterceptor("Agents")]
    public Expression<Func<Agent, Boolean>> OnQueryAgents()
    {
        //Agent is a Person(1), Educator(2), Student(3), or Other Person(13); allow if scope permissions exist
    return ag =>
               (ag.AgentType.AgentTypeId == 1 || ag.AgentType.AgentTypeId == 2 || ag.AgentType.AgentTypeId == 3 || ag.AgentType.AgentTypeId == 13) &&                
            ag.Person.OrganizationPersons.Count<OrganizationPerson>(op =>
                op.Organization.ScopePermissions.Any<ScopePermission>
                    (p => p.ApplicationRoleAccount.Account.UserName == HttpContext.Current.User.Identity.Name && p.ApplicationRoleAccount.Application.ApplicationId == 124) ||
                op.Organization.HierarchyDescendents.Any<OrganizationsHierarchy>(oh => oh.AncestorOrganization.ScopePermissions.Any<ScopePermission>
                    (p => p.ApplicationRoleAccount.Account.UserName == HttpContext.Current.User.Identity.Name && p.ApplicationRoleAccount.Application.ApplicationId == 124))) > 0; 
    }

The query interceptors for Person, Student, Referral are all very similar, ie they traverse multiple same/similar tables to look for ScopePermissions as above.

Sample Query

This sample query is just that, a sample, intended to illustrate to third parties how to access the data using the provided web service. I realize a production query wouldn't have that many expands. (But also remember that to get the entire object in the OOP sense I need an Agent, Person, and Student row.)

var referrals =
            (from r in service.Referrals
                 .Expand("Organization/ParentOrganization")              
                 .Expand("Educator/Person/Agent")
                 .Expand("Student/Person/Agent")
                 .Expand("Student")
                 .Expand("Grade")
                 .Expand("ProblemBehavior")
                 .Expand("Location")
                 .Expand("Motivation")
                 .Expand("AdminDecision")
                 .Expand("OthersInvolved")
             where
                 r.DateCreated >= coupledays &&
                 r.DateDeleted == null
             select r);

Any suggestions or tips would be greatly associated, for fixing my current implementation or in developing a new one, with the caveat that existing database logic can't be changed (though I can add to it) and that ultimately I need to expose a large portion of the database via a web service that limits data access to the data authorized for, for the purpose of data integration with multiple outside parties. These outside parties will be performing regular batch jobs to import our data into their database/data-warehouse.

THANK YOU!!!

UPDATE: Posted this issue on MSDN, received similar feedback. http://social.msdn.microsoft.com/Forums/en-US/adodotnetdataservices/thread/1ccfc96c-dd35-4879-b36b-57e915d5e02f/

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

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

发布评论

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

评论(1

缺⑴份安定 2024-09-02 23:30:11

我只是在这里猜测......但是进行这么多扩展几乎从来都不是一个好主意。该查询无疑会扩展成一些非常糟糕的 SQL,这很容易导致超时。

将 TPT 添加到等式中,事情只会变得更糟:(

Alex

I'm just guessing here... but doing that many expands is almost never a good idea. The query will undoubtedly expand into some pretty awful SQL, that could easily cause timeouts.

Add TPT to the equation and things only get worse :(

Alex

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