2012-06-14 64 views
0

我在我的数据库中有这样的表,如CustomerMemberInstructor, Employee等。这些用户中的每一个都有他的电子邮件地址。我需要检查是否已经有一个给定的电子邮件用户。我在想:检查是否存在多个表中的值

  • 检查每个表,像这样:
public bool IsEmailAddressExists(string email) 
    { 
     if (!Context.Customers.Any(c => string.Equals(c.Email, email, StringComparison.InvariantCultureIgnoreCase))) 
      if (!Context.Members.Any(m => string.Equals(m.Email, email, StringComparison.InvariantCultureIgnoreCase))) 
       ... 
    } 
  • 选择所有电子邮件和检查:
public bool IsEmailAddressExists(string email) 
    { 
     var emails = Context.Customers.Select(c => c.Email).Union(Context.Members.Select(m => m.Email))...; //other unions 
     return emails.Any(e => string.Equals(e, email, StringComparison.InvariantCultureIgnoreCase)); 
    } 

有更多的表和许多用户,所以我想知道什么是最有效的方式来实现这种类型检查。

谢谢。

+0

不要做'select','any'会更有效率。但是我不能看到更多的选择,因为你需要搜索每个表格。如果你真的需要额外的性能,也许你可以像存储过程一样。另一种方法是将所有电子邮件地址存储在一张表中,并将它们与关系关联起来(尽管还有更多的工作) – musefan

+0

@musefan,谢谢你的回答。我想到了两种选择。我会考虑存储过程,并且对于个人电子邮件表 - 我不允许更改数据库模式。 – Zabavsky

回答

1

在纯SQL,这将是你最有效的,因为它停止,因为它击中一个比赛尽快搜索:

...作为一个存储过程:

CREATE PROCEDURE EmailExists 
    @email varchar(254) = NULL 
AS 
BEGIN 
    -- SET NOCOUNT ON added to prevent extra result sets from 
    -- interfering with SELECT statements. 
    SET NOCOUNT ON; 

    DECLARE @emailExists bit 

    SET @emailExists = 0 

    SELECT @emailExists = 1 WHERE EXISTS(SELECT 1 FROM Customer WHERE email = @email) 
    IF @emailExists = 0 
    BEGIN 
     SELECT @emailExists = 1 WHERE EXISTS(SELECT 1 FROM Member WHERE email = @email) 
     IF @emailExists = 0 
     BEGIN 
      SELECT @emailExists = 1 WHERE EXISTS(SELECT 1 FROM Instructor WHERE email = @email) 
      IF @emailExists = 0 
      BEGIN 
       SELECT @emailExists = 1 WHERE EXISTS(SELECT 1 FROM Employee WHERE email = @email) 
      END 
     END 
    END 

    SELECT @emailExists 
END 

...作为一个标量值函数:

CREATE FUNCTION EmailExists 
(
    @email varchar(254) 
) 
RETURNS bit 
AS 
BEGIN 
    DECLARE @emailExists bit 

    SET @emailExists = 0 

    SELECT @emailExists = 1 WHERE EXISTS(SELECT 1 FROM Customer WHERE email = @email) 
    IF @emailExists = 0 
    BEGIN 
     SELECT @emailExists = 1 WHERE EXISTS(SELECT 1 FROM Member WHERE email = @email) 
     IF @emailExists = 0 
     BEGIN 
      SELECT @emailExists = 1 WHERE EXISTS(SELECT 1 FROM Instructor WHERE email = @email) 
      IF @emailExists = 0 
      BEGIN 
       SELECT @emailExists = 1 WHERE EXISTS(SELECT 1 FROM Employee WHERE email = @email) 
      END 
     END 
    END 

    -- Return the result of the function 
    RETURN @emailExists 
END 

在C#中使用LINQ,你可以使用任何分机和||运营商。由于Any通常在SQL中被翻译为EXISTS并且||的评估C#中的操作符是懒惰的,只要到达第一个电子邮件,评估就会停止。

bool emailExists = customerEmails.Any(e => string.Equals(e, email, StringComparison.InvariantCultureIgnoreCase)) 
        || memberEmails.Any(e => string.Equals(e, email, StringComparison.InvariantCultureIgnoreCase)) 
        || instructorEmails.Any(e => string.Equals(e, email, StringComparison.InvariantCultureIgnoreCase)) 
        || employeeEmails.Any(e => string.Equals(e, email, StringComparison.InvariantCultureIgnoreCase)); 
+0

谢谢JamieSee。我将使用第二种方法,但可能在将来创建一个'FUNCTION'。 – Zabavsky

5

这听起来像你有几个选项。

创建视图。您可以在数据库中创建一个仅显示电子邮件地址的视图。假设你正在使用MSSQL Server中,是这样的:

CREATE VIEW EmailView AS 
SELECT Email from Customers 
UNION ALL 
SELECT Email from Instructors 
.... 

...然后使用绑定到视图,以便您可以检查电子邮件列表的实体,看看是否电子邮件已经存在。查看documentation了解更多信息。

正常化您的数据库。这些表中的每一个表是否共享电子邮件以外的常见信息,比如名字和/或姓氏?您可能需要花时间重新组织数据模型,将这些信息放入“人员”表中,然后将其他表格向外键入。 (这也将有助于如果你的用户是两个不同的东西,比方说,客户和讲师。)

+2

Bah,它是咖啡前的 - 你也可以使用存储过程来产生一点结果。 – Ross

+0

谢谢罗斯。是的,有一个像名字和姓氏这样的常见信息,但正如我上面所说的,我无法更改数据库模式。 – Zabavsky