繁体   English   中英

ASP.NET 核心MVC列表<model> .包含(模型)</model>

[英]ASP.NET Core MVC List<Model>.Contains(Model)

我有这个 class:

public class UserSet
{
    public int One { get; set; }
    public string Two { get; set; }
    public string Three { get; set; }
}

还有一个 static class:

public static class AllUsers
{
    public static List<UserSet> Usersc = new List<UserSet>();
}

我总是创建新的UserSet ,然后将其存储在Usersc中。 基本上我这样做:

Data.UserSet setupSet = new Data.UserSet()
        {
            One = name,
            Two = OsCislo,
            Three = User.Identity.Name
        };

然后我存储它。

Data.AllUsers.Usersc.Add(setupSet)

现在我想做的是:

  1. 定义设置集
  2. 检查 setupSet 是否在 Usersc 中。
  3. 如果一个(来自我的setupSet)在Usersc中,那么
    3a) 如果 setupSet 在 Userc 中并且一切都相等,那么不要做任何事情。
    3b)如果有什么不同,则删除 AllUsers 中的旧 UserSet 并插入新的

在代码中,它将如下所示:

Data.UserSet setupSet = new Data.UserSet()
        {
            One = name,
            Two = OsCislo,
            Three = User.Identity.Name
        };

if (Data.AllUsers.Usersc.Select(s => s.One).ToList().Contains(User.Identity.Name))
{
    // Always returns false for some reason
    if (!Data.AllUser.Usersc.Contains(setupSet))
    {
        Data.AllUsers.Usersc.Remove(Data.AllUsers.Usersc.Where(s => s.One == User.Identity.Name).ToList().First());
        Data.AllUsers.Usersc.Add(setupSet);
    }
}
else
{
    Data.AllUsers.Usersc.Add(setupSet);
}

如您所见,问题出在我的 if 语句中,我尝试获取 setupSet 是否在 Usersc 中,但由于某些奇怪的原因,即使 setupSet 应该在其中,它总是返回 false。

即使 setupSet 应该在里面

static在任何类型的 Asp.Net 项目中很少使用是有原因的:有多个线程处理您的请求,如果它们都在同一个List<>上争吵,那就是灾难的根源。

要么使用同步集合(如ConcurrentSet<>ConcurrentBag<> ),要么使用粗略的锁定机制,或者确保您不会践踏另一个线程的列表访问权限。

或者更好的是,使用数据库来存储数据。 这就是它的用途,而且大多数 DBMS 都是事务性的,因此它们为您安全地处理多线程访问。

这是因为您的代码行 Data.AllUser.Usersc.Contains(setupSec) 比较引用 - 而不是列表中对象的属性值。

您在顶部创建 setupSet object 而不将其添加到列表中 - 因此此列表不包含它。 尽管两个对象具有完全相同的 .net 属性值,但它们是两个不同的对象。 因此 list.Contains() 返回 false。

因此,要解决您的问题,有两种方法:

  1. 不要使用 List 的 Contains() 方法 - 并使用 LINQ 表达式比较对您理解 UserSet class 的 2 个对象的相等性至关重要的属性

  2. 绝对更好 - 在您的 UserSet class 中实现 Equals 方法,这将告诉 CLI 如果涉及到您的 class,您将什么理解为 EQUAL。

看看下面的代码(请记住,这是一个幼稚的实现):

void Main()
{
    var myList = new List<SomeClass>();

    var o1 = new SomeClass{SomeProperty = "foo"};

    myList.Add(o1);

    var o2 = new SomeClass{SomeProperty = "foo"};

    if(myList.Contains(o2))
    {
        "List Contains element".Dump();
    }
    else{
        "List does not contain element".Dump();
    }

}



private class SomeClass{
    public string SomeProperty {get;set;}

    public override bool Equals(object obj)
    {
        var casted = obj as SomeClass;
        if(casted == null) return false;
        if(string.Equals(casted.SomeProperty, this.SomeProperty)) return true;
        return false;
    }
}

在这里,我告诉 .NET 通过覆盖 {public bool Equals(object obj)} 方法,我的 SomeClass 的 2 个实例相等对我意味着什么。

在该方法内部,如果 SomeProperty 的值相同,我会写 2 个对象相等。

if(string.Equals(casted.SomeProperty, this.SomeProperty)) return true; 

因此在控制台中,我可以看到“列表包含元素”。 如果您删除该覆盖 Equal,控制台将显示“列表不包含该元素”。

最后但并非最不重要的是,正如 Blindy 所写 - 使用线程安全集合。 它将使您的示例更好(但是我不相信线程是您描述的问题)。

您还可以深入研究 Entity Framework 中的内存数据库 - 您不必创建 static class 和 static 元素集合(相信是缓存数据库的模拟)。 超级简单

var options = new DbContextOptionsBuilder<ApplicationDbContext>()
                    .UseInMemoryDatabase(databaseName: "My_DB")
                    .Options;
            var context = new ApplicationDbContext(options);

暂无
暂无

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

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