Marten: Inheritance issue after upgrade from 3.2.0 to 3.3.0 [Regression]

Created on 1 Mar 2019  路  6Comments  路  Source: JasperFx/marten

After upgrading from 3.2.0 to 3.3.0, I get an exception when trying to store documents that use inheritance. Note the issue is still present in 3.4.0.

Here's what my classes look like (throws when I try to store an instance of LinuxPolicy):

public class LinuxPolicy : OsPolicy
{

}

public abstract class OsPolicy : BasePolicy
{

}

public abstract class BasePolicy : IPolicy
{
    public Guid VersionId { get; set; } = Guid.NewGuid();
    public Guid DocumentId { get; set; } = Guid.NewGuid();
}

public interface IPolicy : IVersioned
{
    PolicyType Type { get; }
    string Name { get; set; }
    string Description { get; set; }
}

public interface IVersioned
{
    /// <summary>The unique ID of a version of the document</summary>
    Guid VersionId { get; set; }

    /// <summary>ID that remains the same for all versions of a document</summary>
    Guid DocumentId { get; set; }
}

And here's what my registration looks like:


For<IPolicy>()
    .Identity(x => x.VersionId)
    .AddSubClassHierarchy();

And the exception:

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.ArgumentException: 'VersionId' is not a member of type 'Acme.Models.IPolicy'
Parameter name: propertyOrFieldName
   at System.Linq.Expressions.Expression.PropertyOrField(Expression expression, String propertyOrFieldName)
   at Marten.Util.LambdaBuilder.<>c__DisplayClass10_0.<ToExpression>b__3(<>f__AnonymousType1`2 acc, MemberInfo member)
   at System.Linq.Enumerable.Aggregate[TSource,TAccumulate](IEnumerable`1 source, TAccumulate seed, Func`3 func)
   at Marten.Util.LambdaBuilder.ToExpression(EnumStorage enumStorage, MemberInfo[] members, ParameterExpression target)
   at Marten.Schema.Arguments.UpsertArgument.CompileUpdateExpression(EnumStorage enumStorage, ParameterExpression call, ParameterExpression doc, ParameterExpression updateBatch, ParameterExpression
mapping, ParameterExpression currentVersion, ParameterExpression newVersion, ParameterExpression tenantId, Boolean useCharBufferPooling)
   at Marten.Schema.DocumentStorage`1.<>c__DisplayClass16_0.<buildSprocWriter>b__0(UpsertArgument x)
   at System.Linq.Enumerable.SelectArrayIterator`2.ToArray()
   at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
   at System.Dynamic.Utils.CollectionExtensions.ToReadOnly[T](IEnumerable`1 enumerable)
   at System.Linq.Expressions.Expression.Block(IEnumerable`1 variables, IEnumerable`1 expressions)
   at Marten.Schema.DocumentStorage`1.buildSprocWriter(DocumentMapping mapping)
   at Marten.Schema.DocumentStorage`1..ctor(DocumentMapping mapping)
   at Marten.Schema.HierarchicalDocumentStorage`1..ctor(DocumentMapping hierarchy)
   --- End of inner exception stack trace ---
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
   at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
   at Marten.Schema.DocumentMapping.Marten.Schema.IDocumentMapping.BuildStorage(StoreOptions options)
   at Marten.Schema.SubClassMapping.BuildStorage(StoreOptions options)
   at Marten.Storage.StorageFeatures.StorageFor(Type documentType)
   at Marten.DocumentSession.Store[T](T[] entities)

Note this issue is not constrained to the use of Identity(), as I get a similar exception if I use .Duplicate() in my registration.

bug

All 6 comments

Adding a simple console app that reproduces this issue:

MartenRepro.zip

Note that if you downgrade this app to 3.2.0, everything works as expected.

Thankfully there weren't that many changes betweeb 3.2.0 and 3.3.0, which made this easier to narrow down - the problem is with the changes made to src\Marten\Util\LambdaBuilder.cs in 8c8a7492ca1edc44cfd9040ac9bcb1fc6acf4790, with the exception occurring @L143.

I'm not really into Linq internals, and I find LambdaBuilder quite difficult to follow, especially after this commit, but I presume the issue is happening because IPolicy inherits from IVersioned, and that case isn't handled.

I'll try to check in in the next few days.

That would be great, thanks!

I also came across this issue in our code base. We use the default property
Guid Id which is inherited into theclasses we store. It works find for Marten 3.2 and throws and exception from 3.3 on that it can not find a property with name Id.

@cocowalla here's the fix :) https://github.com/JasperFx/marten/pull/1235
Should be released with 3.5.0 version.

Was this page helpful?
0 / 5 - 0 ratings