2015-01-22 2 views
0

Я работаю над этим более недели, и в настоящее время ушел из стресса, Надеюсь, вы, ребята, можете избавить меня от моих страданий. Я приветствую Если вы можете предложить общий подход. Хорошо, мы здесь,Add Remove Update Список классов в C#

Я нахожусь на кривой обучения и создаю небольшое приложение для чата с использованием SignalR, MVC, JSON, jquery.

У меня есть класс Чаттера, который содержит список классов ChatMsg (Msgs). Как показано в методе GetData(), я получаю мои классы, заполненные из базы данных, в список. Как видите, список Chatter содержит некоторые переменные, включая список ChatMsg. Это приведет к любым изменениям в таблице (новые сообщения чата). До сих пор это нормально работает. [Добавить деталь]

[Serializable] 
public class Chatter 
{ 
    public string Name { get; set; } 
    public bool Open { get; set; } 
    public DateTime LastMsg { get; set; } 
    public IEnumerable<ChatMsg> Msgs { get; set; } 
} 

[Serializable] 
public class ChatMsg 
{ 
    public DateTime MsgCreated { get; set; } 
    public string MsgType { get; set; } 
    public string MsgBody { get; set; } 
} 

public List<Chatter> GetData() 
{ 

    Dictionary<string, List<ChatMsg>> dcm = new Dictionary<string, List<ChatMsg>>(); 
    List<Chatter> lcm = new List<Chatter>(); 

    using (var connection = new SqlConnection(_connString)) 
    { 
     connection.Open(); 
     using (var command = new SqlCommand(@"SELECT [Sender], [Receiver], [Body], [MessageCreated] FROM [dbo].[Chat] WHERE [Receiver] = @Name AND [Seen] = @Seen", connection)) 
     { 
      command.Parameters.Add(new SqlParameter("@Name", "Fan"));//Test val 
      command.Parameters.Add(new SqlParameter("@Seen", "0"));//Test val 
      command.Notification = null; 

      var dependency = new SqlDependency(command); 
      dependency.OnChange += new OnChangeEventHandler(dependency_OnChange); 

      if (connection.State == ConnectionState.Closed) 
       connection.Open(); 

      var reader = command.ExecuteReader(); 

      while (reader.Read()) 
      { 

       List<ChatMsg> cm = new List<ChatMsg>(); 
       cm.Add(item: new ChatMsg { MsgCreated = Convert.ToDateTime(reader["MessageCreated"]), MsgType = "from", MsgBody = (string)reader["Body"] }); 

       if (dcm.ContainsKey((string)reader["Sender"])) 
       { dcm[(string)reader["Sender"]].Add(item: new ChatMsg { MsgCreated = Convert.ToDateTime(reader["MessageCreated"]), MsgType = "from", MsgBody = (string)reader["Body"] }); } 
       else { dcm.Add((string)reader["Sender"], cm); } 
      } 
     } 
    } 

    foreach (KeyValuePair<string, List<ChatMsg>> pair in dcm) 
    { 
     lcm.Add(item: new Chatter { Name = pair.Key, Open = true, LastMsg = DateTime.UtcNow, Msgs = pair.Value }); 
    } 
    // Updateting [Seen] = 1 here 
    return lcm; 
} 

Теперь, если это новый экземпляр, я помещаю этот список Chatters в Session.

Каждый раз, когда getData() получает новые данные, я хотел бы проверить свою сессию ["ChatHistory"], и если Parent.Name существует, я хотел бы обновить Parent и Addrange до Msgs, если не объявление нового родителя из getData(). Я борюсь за следующий код.

public string receiveMessages() 
{ 
    if (Session["ChatHistory"] == null) Session["ChatHistory"] = new List<Chatter>(); 
    List<Chatter> lc = (List<Chatter>)Session["ChatHistory"]; 

    ChatRepository chatRepository = new ChatRepository(); 

    List<Chatter> c = (List<Chatter>)chatRepository.getData(); 

    //havent tested below 
    foreach (Chatter e in c) 
    { 
     var temp_lc = lc.Find(n => n.Name == e.Name);// Can we avoid linq? 
     if (temp_lc == null) 
     { 
      lc.Add(e); 
     } 
     else 
     { 
      // How to Addrange to Msgs? 
     } 

    } 

    var serializer = new JavaScriptSerializer(); 
    var t = serializer.Serialize(lc); 
    return t; 
} 
  1. Как обновить список класса в списке класса?
  2. Как удалить элемент из списка классов?

Большое вам спасибо!

ответ

1

Рассмотрите использование имен переменных, таких как chatters и chatterHistory вместои lc. Это значительно облегчает чтение.

Попробуйте переписывать foreach в receiveMessages() так:

foreach (Chatter e in c) 
{ 
    var temp_lc = lc.Where(x => x.Name == e.Name).SingleOrDefault(); 
    if (temp_lc == null) 
    { 
     lc.Add(e); 
    } 
    else 
    { 
     temp_lc.Msgs = temp_lc.Msgs.Concat(e.Msgs).ToList(); 
    } 
} 

Если temp_lc существует, temp_lc.Msgs.Concat(e.Msgs).ToList() будет сцепить Msgs свойство с e.Msgs. ToList() преобразует его в List<ChatMsg>, а затем мы можем назначить все это на temp_lc.Msgs.

Это последний шаг очень важен, потому что Concat()не мутировать (изменение) объекта он вызывается на - вместо этого, он возвращает новый объект, который мы тогда можно назначить обратно temp_lc.Msgs.

+0

Нейт, большое спасибо за быстрый ответ. Очень ценю это. Можно ли проиллюстрировать, как удалить элемент из lc.Msgs (одно сообщение от пользователя) и lc (весь пользователь)? – Udaan

+0

Также я нашел 'var temp_lc = lc.Find (n => n.Name == e.Name);' выполняет ту же работу, что и ваш код 'var temp_lc = lc.Where (x => x.Name == e.Name) .SingleOrDefault(); 'В чем разница? Есть ли преимущество в вашем коде или просто предпочтение? Благодарю. – Udaan

+0

Вы правы: 'lc.Find (n => n.Name == e.Name)' делает то же самое, что и 'lc.Where (x => x.Name == e.Name) .SingleOrDefault () '. Это в основном вопрос личных предпочтений. Причина, по которой мне нравится второй способ, заключается в том, что она дает вам немного большую гибкость. 'Find' всегда возвращает результат или' null', тогда как 'Where' возвращает выражение. Если вы решили реорганизовать свой код, вы можете легко отключить вызов «SingleOrDefault» с помощью 'Any', или' Count', или любого другого метода расширения LINQ. –