#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));
}