-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Proof of concept for supporting compound primary keys in LINQ with the EF Core Provider. #1161
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,6 +15,8 @@ | |
|
|
||
| using System; | ||
| using System.Collections; | ||
| using System.Collections.Generic; | ||
| using System.Linq; | ||
| using MongoDB.Bson.IO; | ||
|
|
||
| namespace MongoDB.Bson.Serialization | ||
|
|
@@ -24,10 +26,25 @@ namespace MongoDB.Bson.Serialization | |
| /// </summary> | ||
| public class BsonSerializationInfo | ||
| { | ||
| #region static | ||
| /// <summary> | ||
| /// Creates anew instance of the BsonSerializationinfo class with an element path instead of an element name. | ||
| /// </summary> | ||
| /// <param name="elementPath">The element path.</param> | ||
| /// <param name="serializer">The serializer.</param> | ||
| /// <param name="nominalType">The nominal type.</param> | ||
| /// <returns>A BsonSerializationInfo.</returns> | ||
| public static BsonSerializationInfo CreateWithPath(IEnumerable<string> elementPath, IBsonSerializer serializer, Type nominalType) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Adding a new public constructor was a breaking change so I added a new static factory method instead. Note: a new public constructor resulted in compile time ambiguity when called with |
||
| { | ||
| return new BsonSerializationInfo(elementPath.ToList(), serializer, nominalType); | ||
| } | ||
| #endregion | ||
|
|
||
| // private fields | ||
| private string _elementName; | ||
| private IBsonSerializer _serializer; | ||
| private Type _nominalType; | ||
| private readonly string _elementName; | ||
| private readonly IReadOnlyList<string> _elementPath; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would suggest to have both: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I understand that there is an additional allocation. I was prioritizing simplicity and correctness over trying to optimize away an allocation. The logic is that an What I didn't want to do was force every user of this class to first test whether Do you think we can eliminate the allocation without complicating how this class can be consumed? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess a related question is: do we need a variable length path at all? Is it sufficient to only support a single level of nesting? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've pushed a commit that has mutually exclusive Note the changes in the users of this class that now have to check whether |
||
| private readonly IBsonSerializer _serializer; | ||
| private readonly Type _nominalType; | ||
|
|
||
| // constructors | ||
| /// <summary> | ||
|
|
@@ -43,13 +60,35 @@ public BsonSerializationInfo(string elementName, IBsonSerializer serializer, Typ | |
| _nominalType = nominalType; | ||
| } | ||
|
|
||
| private BsonSerializationInfo(IReadOnlyList<string> elementPath, IBsonSerializer serializer, Type nominalType) | ||
| { | ||
| _elementPath = elementPath; | ||
| _serializer = serializer; | ||
| _nominalType = nominalType; | ||
| } | ||
|
|
||
| // public properties | ||
| /// <summary> | ||
| /// Gets or sets the dotted element name. | ||
| /// Gets the element name. | ||
| /// </summary> | ||
| public string ElementName | ||
| { | ||
| get { return _elementName; } | ||
| get | ||
| { | ||
| if (_elementPath != null) | ||
| { | ||
| throw new InvalidOperationException("When ElementPath is not null you must use it instead."); | ||
| } | ||
| return _elementName; | ||
| } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Gets element path. | ||
| /// </summary> | ||
| public IReadOnlyList<string> ElementPath | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Given this is a collection of paths, shouldn't this be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think so. There is only ONE "path". The one path is composed of a series of "element names". So path is not plural. Another way to say it: this is not a collection of paths. A path is a collection of element names. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK. |
||
| { | ||
| get { return _elementPath; } | ||
| } | ||
|
|
||
| /// <summary> | ||
|
|
@@ -92,20 +131,21 @@ public object DeserializeValue(BsonValue value) | |
| /// </summary> | ||
| /// <param name="newSerializationInfo">The new info.</param> | ||
| /// <returns>A new BsonSerializationInfo.</returns> | ||
| [Obsolete("This method is no longer relevant because field names are now allowed to contain dots.")] | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We never call this method. Should we delete it? Technically that's a breaking change, but the method no longer works reliably anyway since the server now allows There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Given that it is a breaking change, marking it as There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This method was "broken" long before this PR. We simply didn't realize it because we never call it. Would it be OK to just delete it? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. While I agree that the inclusion of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not proposing we make any changes to this method. I'm merely pointing out that it's already broken, and that we don't use it. Although I do wish we could just delete it. |
||
| public BsonSerializationInfo Merge(BsonSerializationInfo newSerializationInfo) | ||
| { | ||
| string elementName = null; | ||
| if (_elementName != null && newSerializationInfo._elementName != null) | ||
| if (ElementName != null && newSerializationInfo.ElementName != null) | ||
| { | ||
| elementName = _elementName + "." + newSerializationInfo._elementName; | ||
| elementName = ElementName + "." + newSerializationInfo.ElementName; | ||
| } | ||
| else if (_elementName != null) | ||
| else if (ElementName != null) | ||
| { | ||
| elementName = _elementName; | ||
| elementName = ElementName; | ||
| } | ||
| else if (newSerializationInfo._elementName != null) | ||
| else if (newSerializationInfo.ElementName != null) | ||
| { | ||
| elementName = newSerializationInfo._elementName; | ||
| elementName = newSerializationInfo.ElementName; | ||
| } | ||
|
|
||
| return new BsonSerializationInfo( | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,6 +13,8 @@ | |
| * limitations under the License. | ||
| */ | ||
|
|
||
| using System; | ||
| using System.Collections.Generic; | ||
| using MongoDB.Bson.Serialization; | ||
| using MongoDB.Driver.Core.Misc; | ||
|
|
||
|
|
@@ -22,6 +24,7 @@ internal class MemberSerializationInfo | |
| { | ||
| // private fields | ||
| private readonly string _elementName; | ||
| private readonly IReadOnlyList<string> _elementPath; | ||
| private readonly IBsonSerializer _serializer; | ||
|
|
||
| // constructors | ||
|
|
@@ -31,8 +34,27 @@ public MemberSerializationInfo(string elementName, IBsonSerializer serializer) | |
| _serializer = Ensure.IsNotNull(serializer, nameof(serializer)); | ||
| } | ||
|
|
||
| public MemberSerializationInfo(IReadOnlyList<string> elementPath, IBsonSerializer serializer) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is an internal class so this is not a publicly breaking change. |
||
| { | ||
| _elementPath = Ensure.IsNotNull(elementPath, nameof(elementPath)); | ||
| _serializer = Ensure.IsNotNull(serializer, nameof(serializer)); | ||
| } | ||
|
|
||
| // public properties | ||
| public string ElementName => _elementName; | ||
| public string ElementName | ||
| { | ||
| get | ||
| { | ||
| if (_elementPath != null) | ||
| { | ||
| throw new InvalidOperationException("When ElementPath is not null you must use it instead."); | ||
| } | ||
| return _elementName; | ||
| } | ||
| } | ||
|
|
||
| public IReadOnlyList<string> ElementPath => _elementPath; | ||
|
|
||
| public IBsonSerializer Serializer => _serializer; | ||
| } | ||
| } | ||