【问题标题】:How can I simplify this LINQ code如何简化此 LINQ 代码
【发布时间】:2013-11-19 09:41:26
【问题描述】:

基本上我在 MVC 中有一个多选列表框,当用户更改选择时,它会返回并更新模型。下面的代码有效,但我只是想知道如何将它放在一个 foreach 循环中,或者是否有更好的方法来更新选择?注意:艺术家和艺术家类型之间存在多对多关系。

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

【问题讨论】:

标签: c# linq entity-framework multi-select


【解决方案1】:

这个用于添加(只需使用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));

编辑:

你可以随时设置

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

这会将 ArtistTypes 设置为您想要的,您无需删除然后添加。

【讨论】:

  • 所以想象在用户编辑之前选择了多选数字 1 和 4。当用户只选择数字 2 和 3 时,代码应该去删除数字 1 和 4 并添加 2 和 3。有没有更好的方法来处理这个问题,或者我仍然需要正确的 2 行代码来添加一个来删除?
  • 它给出的不能将 System.Iqueryable 转换为 Generic.Collection ?
  • 一个简单的问题,如果你能回答.. 例如,我将如何删除艺术家?我需要先清除所有艺术家类型,还是在我使用 this._db.Entry(artist).State = EntityState.Deleted; 删除艺术家时自动清除? ?
  • @akdurmus 我不是 EF 专家 :) 我想 _db.Artists.Delete(artist) 可以,你能做到吗?
【解决方案2】:

我看到了两个“修复”:

1) 你不需要关心列表里面有什么,因为你要更新你可以从头开始的选择列表,所以删除部分变成了

artist.ArtistTypes.Clear();

2) 现在您再次填写列表。 ToList() 应该不需要,因为您正在执行 .Where() 来获取数据,并且您可以利用 Linq 的惰性机制,因此您只会读取您实际使用的数据。您还可以拆分行以提高可读性(没关系:在您执行 foreach() 之前,数据库不会被实际命中。

//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) (未经测试,在我的脑海中)实现您所做的比较的另一种方法是通过自定义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 }));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-19
    • 2016-11-16
    • 1970-01-01
    • 2018-01-27
    相关资源
    最近更新 更多