2013-11-19 4 views
1

В основном у меня есть список из списка мультиселектов в MVC, и когда пользователь меняет выбор, он возвращается и должен обновлять модель. ниже работает код, но мне просто интересно, как я могу поместить его в один цикл foreach или есть лучший способ обновления выбора? Примечание. Существует множество отношений между художником и художником.Как я могу упростить этот код LINQ

foreach (var artistTtype in this._db.ArtistTypes.ToList().Where(artistTtype => artist.ArtistTypes.Contains(artistTtype))) 
{ 
    artist.ArtistTypes.Remove(artistTtype); 
} 

foreach (var artistTtype in this._db.ArtistTypes.ToList().Where(artisttype => vm.SelectedIds.Contains(artisttype.ArtistTypeID))) 
{ 
    artist.ArtistTypes.Add(artistTtype); 
} 
+0

Взгляните на это: [? Как я должен удалить все элементы в DbSet] (http://stackoverflow.com/questions/10448684/how-should-i-remove-all-elements-in -a-dbset). Может быть, проще выполнить SQL, чтобы удалить элементы коллекции 'ArtistType' (указав' ArtisId' в предложении 'where'). –

ответ

2

Это для добавления (просто используйте AddRange):

artist.ArtistTypes.AddRange(this._db.ArtistTypes 
     .Where(artisttype => vm.SelectedIds.Contains(artisttype.ArtistTypeID))); 

Эта для удаления (используйте ForEach):

this._db.ArtistTypes 
     .Where(artistTtype => artist.ArtistTypes.Contains(artistTtype)).ToList() 
       .ForEach(x=>artist.ArtistTypes.Remove(x)); 

EDIT:

вы всегда можете установить

artist.ArtistTypes = this._db.ArtistTypes 
     .Where(artisttype => vm.SelectedIds.Contains(artisttype.ArtistTypeID)).ToList(); 

это установит ArtistTypes на то, что вы хотите, вам не нужно удалять, а затем добавлять.

+0

так представьте, прежде чем пользователь отредактировал несколько вариантов выбора 1 и 4. когда пользователь идет и только выбирает номер 2 и 3, код должен идти и удалять номера 1 и 4 и вместо этого добавлять 2 и 3. есть ли лучший способ справиться с этим, или мне все еще нужно править 2 строки кода для добавления одного для удаления? – akd

+0

@akdurmus see edit in my answer – wudzik

+0

Он не может преобразовать System.Iqueryable <> в Generic.Collection <>? – akd

0

Я вижу два «исправления»:

1) Вам не нужно заботиться о том, что внутри списка, так как вы собираетесь обновить список вариантов, вы можете начать с нуля, так что удаление часть становится

artist.ArtistTypes.Clear(); 

2) Теперь вы снова заполните этот список. ToList() не требуется, поскольку вы выполняете .Where(), чтобы получить данные, и вы можете использовать ленивые механизмы Linq, чтобы вы могли читать только данные, которые вы используете. Можно также разделить линии для повышения читаемости (это не имеет значения:. Пока не делать Еогеасп() БД не будет на самом деле удар

//note that the .ToList() is gone 
var query = this._db.ArtistTypes.Where(artisttype => vm.SelectedIds.Contains(artisttype.ArtistTypeID); 
foreach (var artistTtype in query)) 
{ 
    artist.ArtistTypes.Add(artistTtype); 
} 

2b) (UNTESTED, с верхней части моей головы) Другой способ реализации сравнения вы делаете через пользовательский IEqualityComparer, переключившись на метод .Intersect(). Это более устойчиво, поскольку, если ваши ключи меняются в модели, вам нужно только изменить компаратор.

// I'm making up "ArtistType", fix according to your actual code 
class ArtistTypeEqualityComparer : IEqualityComparer<ArtistType> 
{ 
    public bool Equals(ArtistType x, ArtistType y) 
    { 
     if (ArtistType.ReferenceEquals(x, null)) return false; 
     if (ArtistType.ReferenceEquals(y, null)) return false; 
     if (ArtistType.ReferenceEquals(x, y)) return true; 

     return x.ArtistTypeId.Equals(y.ArtistTypeId); 
    } 
    public int GetHashCode(ArtistType obj) 
    { 
     return obj.ArtistTypeId.GetHashCode(); 
    } 
} 

// And then the "add" part simplifies 

artist.ArtistTypes.AddRange(this._db.ArtistTypes.Intersect(vm.SelectedIds.Select(x => new ArtistType{ ArtistTypeId = x })); 
Смежные вопросы