Удалить запись списка привязок из результатов Linq. — 2 птицы в одном кадре?

#c# #linq

#c# #linq

Вопрос:

Этот запрос возвращает левое внешнее соединение из двух таблиц.

   var q = from adu in dtAdsUsers.AsEnumerable()
                        join elu in dtElUsers.AsEnumerable() on adu.Field<string>("samAccountName") equals elu.Field<string>("UserLogin") into gj
                        from au in gj.DefaultIfEmpty() //where au.Field<string>("UserLogin")==string.Empty
                        select
                        new
                        {
                            samAccount = adu.Field<string>("samAccountName"),
                            samb = (au == null ? string.Empty : au.Field<string>("UserLogin"))

                        };
  

Теперь удалите записи из dtAdusers, который привязан к bindinglist bUserList, используя код, подобный этому

     foreach (var o in q)
                {

                if (o.samb != "")
                    {
                    Debug.WriteLine(o.samAccount);
                    IEnumerable<ADSUtilities.User> ud = from u in bUserList.AsEnumerable()
                                                        where u.sAMAccountName == o.samAccount
                                                        select u;

                    bUserList.RemoveAt(bUserList.IndexOf(ud));


                    }

                }
  

bUserList.RemoveAt(bUserList.indexOf(ud)) выдает недопустимое исключение приведения
1). Как это решить?
2). есть ли способ Linq удаления записей без итерации?

Ответ №1:

ud это IEnumerable в то время как элементы в bUserList предположительно не из, IEnumerable вот почему bUserList.IndexOf(ud) произойдет сбой.

Если запрос для ud действительно может привести к появлению нескольких объектов, тогда вам нужно удалить их 1 к 1 следующим образом

 foreach(var doomed in ud)
    bUserList.Remove(doomed);
  

Если предполагается, что запрос для ud возвращает только один элемент, вам следует изменить его на:

  ADSUtilities.User ud = bUserList.AsEnumerable().First(u => u.sAMAccountName == o.samAccount);
  

Тогда вы можете сделать: bUserList.Remove(ud);

Используйте FirstOrDefault , если запрос не может привести ни к каким объектам. Это вернет default(T) (который null для ссылочных типов) вместо того, чтобы генерировать исключение.

Не существует реального «Linq way» удаления элементов из списка, потому что вы не можете перечислять список и удалять элементы из него одновременно. Это привело бы к исключению. Поэтому вам всегда нужно сначала определить элементы, которые вы хотите удалить, сохранить их в отдельном списке, а затем удалить их. Вы могли бы создать метод расширения для, если вам это требуется чаще. Что-то вроде этого:

  public static RemoveIf<T>(this IList<T> list, Predicate<T> cond)
 {
     var doomed = list.Where(cond).ToList();
     doomed.ForEach(x => list.Remove(x));
 }