棘手的LINQ功能

时间:2011-05-17 16:30:40

标签: linq-to-sql


在我的应用程序中,我有像User,Person和Group这样的实体,它们也是IMember类型(因为它们可以是某个用户组的成员)。我的MS SQL 2008数据库中还有用户,人员和组表,它们保存相应的实体数据 我经常需要将所有这些实体或实体集合作为一个集合 - 例如,当我获得某个组的所有成员或我正在按其名称或其他任何方式搜索成员时。为此,我想要一个应用程序方法,其中确定对应于IMember类型的所有表(将来可能会添加一些表)。这个函数应该返回一个集合中的所有检索对象,我也希望函数接受一些条件来为每个表执行所需的请求,因为我将调用上面的一些更具体的函数。例如,如果我想获得所有IMember的名称为“nick”,则该函数应在User,Person和Group表中搜索“nick”。传递这些条件并保持最终SQL查询最佳的最佳方法是什么? 谢谢!

1 个答案:

答案 0 :(得分:0)

首先,我想以我理解的方式重述您的问题。您在数据库中有一些表,如下所示:

--SQL DDL
CREATE TABLE [User](
  Name varchar(25),
  Location varchar(50)
  --Other User specific columns like login, expireDate etc.
)

CREATE TABLE Person(
  Name varchar(25),
  Location varchar(50)
  --Other Person specific columns like Birthday etc.
)

这些表都有一个代表成员的 base 列。在代码中,您有一个IMember接口定义如此。 (您使用的是C#还是VB?)

//C# code
interface IMember
{
    string Name { get; set; }
    string Location { get; set; }
}

'VB code
Interface IMember
    Property Name As String
    Property Location As String
End Interface

您希望将所有IMembers作为逻辑单一集合进行操作。有关您可能拥有的任何限制或偏好的更多信息将是很好的,例如:它是否可行/您是否有权更改数据库的布局?是否可以将存储过程添加到数据库以便于对集合进行操作。它只是选择您需要的成员还是您需要能够插入/更新/删除成员?将新的派生成员表添加到数据库时,是否可以使用最少量的更改重新编译代码。此外,如果您要求提供可能包含代码片段的解决方案,那么很高兴知道您喜欢哪种.NET语言(如果有的话)。对于许多人来说,“最优”还有很多含义,在代码方面最简单吗?最快的?往返次数最少?真的是最理想的要求还是“足够好”?

那就是说,这里有一些可能的解决方案

可能的解决方案#1: 您可以像这样重组表:

--SQL DDL
CREATE TABLE Member(
  MemberID int PRIMARY KEY,
  Name varchar(25)
  Location varchar(50)
)

CREATE TABLE User(
  MemberID int FOREIGN KEY,
  --Other User specific columns like login, expireDate etc.
)

CREATE TABLE Person(
 MemberID int FOREIGN KEY,
  --Other Person specific columns like Birthday etc.
)

使用新结构,您的问题变得更加简单。您可以使用linq-to-sql在Member表上SELECTUPDATEDELETE(使用级联删除设置)。稍后添加的任何新表将遵循使用外键加入Member表的相同形式,并且不需要从任何应用程序重新编译。如果这不是一个可能的解决方案,请解释原因。

可能的解决方案#2 我们假设由于遗留问题或权限问题,上述情况无法实现。是否可能设置视图或存储过程来模仿上述解决方案。类似于以下存储过程的内容将允许您按名称选择所有成员。如果需要,插入/更新/删除可能会更复杂。

CREATE PROCEDURE GetMemberByName @Name varchar(25) AS
BEGIN
        SELECT Name, Location FROM [User]
  UNION SELECT Name, Location FROM Person
  --Add more tables here when available
  WHERE NAME = @Name
END

同样,这是一个在添加新表时无法重新编译代码的解决方案。

可能的解决方案#3 最后,代码内解决方案可能更符合您的需求。我的问题再次与细节有关。添加新表时,您是否要重新编译L2S类?如果是,您可能只能将IMember接口添加到每个表类中,然后在派生的datacontext的部分类中公开IQueryable<IMember> / IQueryable(Of IMember))属性,该属性提供{{1涉及的所有表。如果不是,您可能必须查询数据库系统表以使所有表都具有所有必需的IMember属性作为列,并选择它们的并集。这似乎是很多工作,如果你不得不走这条路,我不会羡慕你。

此外,将更新/插入/删除写回相应表的可能要求可能需要遍历可能的表以更改正确的表。这些表是否具有uniq w.r.t的密钥。所有成员表。这是一个很好的例子,GUID会闪耀,因为如果你有一个姓名为Joe的用户和一个名字为Joe的人,并且他们碰巧有相同的代理键1234,那么一旦该实体在一个集合中IMember,你怎么知道更新/插入/删除什么?

摘要我很抱歉,如果我因为要求更多详细信息而感到挑剔,那么人们回答特定明确定义的问题要容易得多。请尝试详细说明您的问题或将其分解为可以更具体回答的较小问题。将相关的DDL包含在您知道的现有表格中,以防止我们猜测,以及您可能已经尝试过的相关代码片段。当人们看到他们可以使用的代码块来帮助你改进它时,它会吸引更多的目光。