简体   繁体   English

我如何简化此LINQ代码

[英]How can I simplify this LINQ code

Basically I have a multiselect list box in MVC and when the user changes selection it will come back and it should update the model. 基本上我在MVC中有一个多选列表框,当用户更改选择时,它会回来并且应该更新模型。 the below code works but I am just wondering how can I put it in a single foreach loop or is there a better way of updating the selection? 下面的代码有效,但我只是想知道如何将其放在单个foreach循环中,或者有更好的方法来更新选择? Note: There is a many to many relationship between artist and artist type. 注意:艺术家和艺术家类型之间存在多对多关系。

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

This for adding (just use AddRange ): 这用于添加(只需使用AddRange ):

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

This for removing (use ForEach ): 用于删除(使用ForEach ):

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

EDIT: 编辑:

you can always set 你可以随时设置

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

this will set ArtistTypes to what you want, you don't need to delete then add. 这会将ArtistTypes设置为您想要的类型,您不需要删除然后添加。

I see two "fixes": 我看到两个“修复”:

1) You don't need to care about what's inside the list, since you're going to update the list of selections you can start from scratch, so the removal part becomes 1)您无需关心列表中的内容,因为您将要更新选择列表,因此可以从头开始,因此删除部分变为

artist.ArtistTypes.Clear();

2) Now you fill the list again. 2)现在,您再次填写列表。 ToList() should not be needed since you're performing a .Where() to get the data, and you can leverage Linq's lazy mechanisms so you'll only read the data you actually use. 因为正在执行.Where()来获取数据,所以不需要ToList(),并且可以利用Linq的惰性机制,以便仅读取实际使用的数据。 You can also split the lines for increased readability (it doesn't matter: until you do the foreach() the db will not be actually hit. 您还可以拆分行以提高可读性(没关系:在执行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) (UNTESTED, off the top of my head) Another way of implementing the comparison you do is through a custom IEqualityComparer , switching to .Intersect() method. 2b)(未经测试,不在我头上)实现比较的另一种方法是通过自定义IEqualityComparer ,切换到.Intersect()方法。 This is way more solid since if your keys change in the model you only have to change the comparer. 这是更可靠的方法,因为如果您的键在模型中发生更改,则只需更改比较器即可。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM