2012-06-14 4 views
0

У меня есть такие таблицы в моей базе данных, как Customer, Member, Instructor, 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 обычно переводится в EXISTS в SQL и evalutation of || оператор в 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. На данный момент я буду использовать второй подход, но, вероятно, создаю «ФУНКЦИЮ» в будущем. – Zabavsky

5

Похоже, у вас есть несколько вариантов.

Создать представление. Вы можете создать представление в базе данных, которое показывает, скажем, только адреса электронной почты. Предполагая, что вы используете MSSQL Server, что-то вроде:

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

... затем, используя объект, связанный с этой точки зрения, так что вы можете проверить список сообщений электронной почты, чтобы убедиться, что электронная почта уже существует. За дополнительной информацией обращайтесь к documentation.

Нормализовать вашу базу данных. У каждой из этих таблиц есть общая информация помимо электронной почты, например, имя и/или фамилия? Возможно, стоит потратить ваше время на реорганизацию вашей модели данных, чтобы поместить эту информацию в таблицу «Персоны», а затем заархивировать ваши другие таблицы. (Это также поможет, если пользователи две разные вещи, скажем, клиент и инструктор.)

+2

Ба, это предварительный кофе, вы также можете использовать хранимую процедуру для получения небольшого результата. – Ross

+0

Спасибо Росс.Да, есть общая информация, такая как имя и фамилия, но, как я сказал выше, я не могу изменить схему базы данных. – Zabavsky

Смежные вопросы