Показать комбинированный результат из несвязанных таблиц (LINQ к SQL)

Обновить

December 2018

Просмотры

1.1k раз

2

Я изо всех сил, чтобы выработать лучший способ показать комбинированный результат от двух несвязанных таблиц с помощью LINQ к SQL (C #). Таблицы EmailAlerts и TextAlerts, каждый с UserName, типа и состояния (плюс другие столбцы, которые отличаются, но нужно только эти три для этого запроса). Для целей отчетности, мне нужно, чтобы получить снимок пользователей, имеющих активное оповещение в системе.

Пример таблицы:

EmailAlerts
UserName    Type    Status
Alice       1   0
Alice       1   0
Alice       1   1
Alice       2   0
Alice       2   1
Alice       2   1
Bob         1   1
Bob         2   1
Mallory     1   1
Mallory     2   1

TextAlerts
UserName    Type    Status
Alice       1   1
Alice       2   0
Alice       2   1
Bob         1   0
Mallory     1   1
Mallory     2   1

Это будет введен в CSV-файл, и конечный результат на примере таблицы, должен выглядеть следующим образом:

Username, ActiveType1Email, ActiveType2Email, ActiveType1Text, ActiveType2Text
Alice, Yes, Yes, No, Yes
Bob, No, No, Yes, No

Таким образом, для каждого уникального пользователя, узнайте, если они имеют активное (статус = 0) по электронной почте или текстовое предупреждение либо типа. Они могут иметь несколько предупреждений для обоих типов. Пользователям хранятся в Sitecore так нет таблицы пользователей.

На данный момент я первым получить все уникальные имена пользователей, а затем цикл через каждый из них, чтобы выяснить, что предупреждает у них есть. Это работает, но это довольно ужасно, поэтому я хотел бы, чтобы найти лучшее решение. Можно ли сделать все это в одном запросе? Будет ли хранимая процедура будет лучшим способом сделать это? Если кто-то может мне точку в правильном направлении, я могу попытаться выяснить код сам, я просто не уверен, лучший способ борьбы с ней.

UPDATE: Вот текущий (некрасиво) код:

public static List<Dictionary<string, string>> GetUserAlertsForCSV()
{
    List<Dictionary<string, string>> alerts = new List<Dictionary<string, string>>();

    var usernames = ((from e in db.EmailAlerts select e.UserName).Union
                    (from t in db.TextAlerts select t.UserName)).Distinct();

    foreach (var username in usernames)
    {
        Dictionary<string, string> d = new Dictionary<string, string>();
        d.Add("username", username);
        bool hasActiveAlert = false;

        var activeType1Email = (from e in db.EmailAlerts
                    join a in db.AlertStatusCodes on e.Status equals a.StatusCode
                    where e.UserName == username
                    && e.Type == (int)AlertType.Type1
                    && a.Description == "active"
                    select e).FirstOrDefault();

        if (activeType1Email != null)
        {
            d.Add("type1email", "Yes");
            hasActiveAlert = true;
        }
        else
        {
            d.Add("type1email", "No");
        }

        // repeat the above for activeType1Text, activeType2Email and activeType2Text

        if (hasActiveAlert)
        {
            alerts.Add(d);
        }
    }

    return alerts;
}

Спасибо,

Аннели

1 ответы

2

Попробуйте это, если что-то может дать вам идею. Моя идея позади этого заключается в использовании связанных подзапросов новый анонимный тип, чтобы хранить всю необходимую вам информацию. Проверьте это:

var usernames = ((from e in db.EmailAlerts select e.UserName).Union
                (from t in db.TextAlerts select t.UserName)).Distinct();
var result =
    from u in usernames
    select new 
    {
        Username = u.Username,
        ActiveType1Email = (from e in db.EmailAlerts
                           where e.UserName == u
                           && e.Type == (int)AlertType.Type1
                           && a.Description == "active"
                           select e).FirstOrDefault();
        /*
         ... and so on repeat for activeType1Text, activeType2Email and activeType2Text

        */
    }

    // and then go trough the result set which is IEnumarable<T> and use it for what you need
    foreach(var a in result)
    { 
      var something = a.ActiveType1Email;
      /* etc. */ 
    }

Предусматривает ли это какой-либо помощи для вас?