Uploaded image for project: 'C# Driver'
  1. C# Driver
  2. CSHARP-739

Linq needs support for private backing fields of public members

    XMLWordPrintableJSON

Details

    • Icon: Improvement Improvement
    • Resolution: Done
    • Icon: Major - P3 Major - P3
    • None
    • 1.8.1
    • None
    • None

    Description

      Currently, it is impossible to have a readonly public member that is backed by a private member take part in LINQ queries. The below example illustrates as much:

      namespace MongoBug
      {
          using System.Collections.Generic;
          using System.Linq;
          using MongoDB.Bson;
          using MongoDB.Bson.Serialization;
          using MongoDB.Driver;
          using MongoDB.Driver.Linq;
          using NUnit.Framework;
       
          /// <summary>
          /// Test fixture showing issue with using LINQ queries against a backing field
          /// </summary>
          [TestFixture]
          public class LinqBugTestFixture
          {
              /// <summary>
              /// The connection string
              /// </summary>
              private const string ConnectionString = "mongodb://localhost:27017/mapping_private_field";
       
              /// <summary>
              /// Gets or sets the database.
              /// </summary>
              /// <value>
              /// The database.
              /// </value>
              private MongoDatabase Database { get; set; }
       
              /// <summary>
              /// Sets up the mapping for mongo.
              /// </summary>
              [TestFixtureSetUp]
              public void MapMongo()
              {
                  var url = new MongoUrl(ConnectionString);
                  var client = new MongoClient(url);
                  this.Database = client.GetServer().GetDatabase(url.DatabaseName);
       
                  this.Database.DropCollection("sampleModels");
       
                  BsonClassMap.RegisterClassMap<SampleModel>(cm =>
                  {
                      cm.MapIdProperty(c => c.Id);
                      cm.MapField("children").SetElementName("Children");
                  });
              }
       
              /// <summary>
              /// Tests revealing the missing  mapping use case.
              /// </summary>
              [Test]
              public void TestShowMissingUseCase()
              {
                  var model = new SampleModel();
                  model.AddChild(new ChildrenModel { Name = "One" });
                  model.AddChild(new ChildrenModel { Name = "Two" });
                  model.AddChild(new ChildrenModel { Name = "Three" });
       
                  var collection = this.Database.GetCollection<SampleModel>("sampleModels");
                  collection.Save(model);
       
                  var fromMongo = (from sample in collection.AsQueryable()
                                   where sample.Children.Any(s => s.Name == "Two")
                                   select sample).FirstOrDefault();
       
                  Assert.AreEqual(model.Id, fromMongo.Id);
              }
       
              #region Model Class
              /// <summary>
              /// Sample Model that shows bug accessing private backing field through LINQ queries
              /// </summary>
              public class SampleModel
              {
                  /// <summary>
                  /// The backing field
                  /// </summary>
                  private IList<ChildrenModel> children;
       
                  /// <summary>
                  /// Initializes a new instance of the <see cref="SampleModel"/> class.
                  /// </summary>
                  public SampleModel()
                  {
                      this.children = new List<ChildrenModel>();
                  }
       
                  /// <summary>
                  /// Gets or sets the id.
                  /// </summary>
                  /// <value>
                  /// The id.
                  /// </value>
                  public ObjectId Id { get; set; }
       
                  /// <summary>
                  /// Gets the strings.
                  /// </summary>
                  /// <value>
                  /// The strings.
                  /// </value>
                  public IEnumerable<ChildrenModel> Children
                  {
                      get { return this.children; }
                  }
       
                  /// <summary>
                  /// Adds a child.
                  /// </summary>
                  /// <param name="toAdd">The child to add.</param>
                  public void AddChild(ChildrenModel toAdd)
                  {
                      this.children.Add(toAdd);
                  }
              }
       
              /// <summary>
              /// The child document
              /// </summary>
              public class ChildrenModel
              {
                  /// <summary>
                  /// Gets or sets the name.
                  /// </summary>
                  /// <value>
                  /// The name.
                  /// </value>
                  public string Name { get; set; }
              }
              #endregion
          }
      }

      Attachments

        Activity

          People

            Unassigned Unassigned
            craig.wilson@mongodb.com Craig Wilson
            Votes:
            3 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: