【问题标题】:Query values in a Dictionary<ObjectId, Class> using LINQ?使用 LINQ 查询 Dictionary<ObjectId, Class> 中的值?
【发布时间】:2012-11-29 20:59:09
【问题描述】:

考虑以下学生和教师的简单示例;

// person
public class Person
{
    public ObjectId Id { get; set; }
    public string Name { get; set; }
    public Person() {
        Id = ObjectId.GenerateNewId(DateTime.Now);
    }
}

// student has a Classroom
public class Student : Person
{
    public string Classroom { get; set; }
}

// teacher has a Dictionary<ObjectId, Student> Students
public class Teacher : Person
{
    [BsonDictionaryOptions(DictionaryRepresentation.ArrayOfDocuments)]
    public Dictionary<ObjectId, Student> Students { get; set; }
    public Teacher() {
        Students = new Dictionary<ObjectId, Student>();
    }
}

class Program
{
    static void Main(string[] args)
    {

        var server = MongoServer.Create("mongodb://localhost/database?safe=true");
        var database = server.GetDatabase("sandbox");
        var collection = database.GetCollection<Teacher>("teachers");
        collection.Drop();

        // create students
        var s1 = new Student() { Name = "s1", Classroom = "foo" };
        var s2 = new Student() { Name = "s2", Classroom = "foo" };
        var s3 = new Student() { Name = "s3", Classroom = "baz" };
        var s4 = new Student() { Name = "s4", Classroom = "foo" };

        // teacher 1
        var t1 = new Teacher() { Name = "t1" };
        t1.Students.Add(s1.Id, s1);
        t1.Students.Add(s2.Id, s2);
        collection.Insert(t1);

        // teacher 2
        var t2 = new Teacher {Name = "t2"};
        t2.Students.Add(s3.Id, s3);
        collection.Insert(t2);

        // add teacher 3 
        var t3 = new Teacher() {Name = "t3"};
        t3.Students.Add(s4.Id, s4);
        collection.Insert(t3);

        // select via key
        var onlyt1 = collection.AsQueryable().Where(t => t.Students.ContainsKey(s1.Id)).ToList();

        Console.WriteLine("onlyt1 : {0}", onlyt1.ToJson());
        Console.ReadLine();
    }
}

我可以通过键(如上所示)进行选择,但是我如何找到所有有学生的教室为“foo”的老师?我想写一些类似的东西;

// select via value
var shouldBeJustT1andT3 = collection.AsQueryable().Where(t => t.Students.Values.Where(s => s.Classroom == "foo")).ToList(); 

【问题讨论】:

    标签: c# .net linq mongodb mongodb-.net-driver


    【解决方案1】:

    您可以使用 Any 来获取在给定教室“foo”中有学生的任何老师:

    List<Teacher> shouldBeJustT1andT3 = collection.Where(
        teacher => teacher.Students.Any(student => student.Classroom == "foo")
    ).ToList(); 
    

    编辑

    由于 Mongo 的 IQueryable 默认不支持 Any,也许你可以只使用 WhereCount 而不是 Any

    List<Teacher> shouldBeJustT1andT3 = collection.Where(
        teacher => teacher.Students.Where(student => student.Classroom == "foo").Count() > 0
    ).ToList(); 
    

    【讨论】:

    • 我把 Linq 改成了; collection.AsQueryable().Where(teacher =&gt; teacher.Students.Any(student =&gt; student.Value.Classroom == "foo")).ToList(); 我现在得到了错误; Any requires that the serializer specified for Students support items by implementing MongoDB.Bson.Serialization.IBsonArraySerializer and returning a non-null result. MongoDB.Bson.Serialization.Serializers.DictionarySerializer2[MongoDB.Bson.ObjectId,EntitySandbox.Student] 是当前的序列化器。`
    • @madebybear 我不确定实现IBsonArraySerializer 有多难。请看我上面的更新,也许这会起作用。
    • 感谢您的帮助,但我现在又遇到了一个错误; Unable to determine the serialization information for the expression: Enumerable.Count&lt;KeyValuePair&lt;ObjectId, Student&gt;&gt;(Enumerable.Where&lt;KeyValuePair&lt;ObjectId, Student&gt;&gt;(teacher.Students, (KeyValuePair&lt;ObjectId, Student&gt; student) =&gt; (student.Value.Classroom == "foo")))我去下载驱动源码看看能不能得到一些线索。
    • @madebybear 可能还会检查实现它所要求的接口是否容易? api.mongodb.org/csharp/1.5/html/…
    【解决方案2】:

    你不能只拥有ICollection&lt;Person&gt; 类型的Students 吗?

    那么你不需要查询字典的值而是平面对象的列表,即where s.ID == x &amp;&amp; s.Classroom == "blah"

    字典仅通过键查找对象才有意义,即t.Students[studentId]


    找老师:看dbaseman的回答,他是对的。

    【讨论】:

    • 我可以只使用 ICollection,但是,我想确保老师不能两次拥有相同的学生密钥。
    • @madebybear:存储不应该确保/强制这样的约束吗?
    • 是的,给老师。不过,我想将 n 个学生存储为老师的财产。
    • @madebybear:不同的老师可以有同一个学生吗?我猜是。那么不是“存储”而是“代表”,对吧?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多