c# - 有趣的Linq to SQL通用基类行为

标签 c# linq-to-sql cil

这是关于 InvalidOperationException 的问题,消息未映射类成员X。

对于框架版本3.5的每个LinqToSql实体,我们的系统之一具有相同的基本实体

我遇到了一个非常奇怪的问题,我开始对此进行研究。我做了一个很小的项目,以便能够更轻松地定位问题。

实体基类

public abstract class EntityBase
{
    public virtual long ID { get; set; }
}

DataContext和实体
[Database(Name = "TestDatabase")]
public class EntitiesDataContext : DataContext
{
    public EntitiesDataContext() :
        base(Settings.Default.TestDatabaseConnectionString, new AttributeMappingSource())
    {
    }
}

[Table(Name = "dbo.MyEntity")]
public class MyEntity : EntityBase
{
    private long _EntityID;

    [Column(Name = "EntityID", Storage = "_EntityID")]
    public override long ID
    {
        get { return _EntityID; }
        set { _EntityID = value; }
    }

    [Column] public string Title;
}

问题是重写的 ID 。我对不同的映射属性/属性名称设置进行了很多改动,但似乎问题不是命名,而是基类。 .NET3.5和.NET4.0之间也有区别。

因此,对于以下陈述,假设
using (var ctx = new EntitiesDataContext())
{
    //statement
}

大约。

和GetTable()是GetTable<MyEntity>().
失败表示未映射类成员EntityBase.ID。异常(exception)。 作品表示预期的行为。

1(在3.5中)工作:
var result = ctx.GetTable().Where(i => i.ID == 2).FirstOrDefault();

2(在3.5中)失败:
var result = ctx.GetTable().FirstOrDefault(i => i.ID == 2);

3(在3.5中)工作:
var result = ctx.GetTable().FirstOrDefault(i => i.ID.Equals(2));

4(在3.5中)工作:
var result = ctx.GetTable().Where(i => true).FirstOrDefault(i => i.ID == 2);

5(在3.5中)工作:
var result = ctx.GetTable().Where(i => i.ID == 2).FirstOrDefault();

6(在4.0中)失败:
var result = ctx.GetTable().Where(i => i.ID == 2).FirstOrDefault()

7(在4.0中)工作:
var result = ctx.GetTable().Where(i => i.ID.Equals(2)).FirstOrDefault();

8(在4.0中)失败(与6冗余)
var result = ctx.GetTable().FirstOrDefault(i => i.ID == 2);

9(在4.0中)工作:
var result = ctx.GetTable().FirstOrDefault(i => i.ID.Equals(2));

10(在4.0中)作品:
ctx.GetTable().Where(i => true).FirstOrDefault(i => i.ID == 2);

所以
我无法弄清楚为什么它在失败的地方失败了。特别是为什么这行得通
var result = ctx.GetTable().Where(i => true).FirstOrDefault(i => i.ID == 2);

如果带有谓词的FirstOrDefault没有?以及为什么Equals在==不起作用的地方工作。

我一直在寻找一些等于和==差异的描述,但是它没有给我答案Where(i => true)...的东西。

似乎与查询无关,而与对象初始化有关。因为:

在4.0工作中:
var result = ctx.GetTable().Where(i => i.ID == 2).Select(i => i.Title).FirstOrDefault();

但 :)

在4.0中,它也可以工作:
var result = ctx.GetTable().FirstOrDefault();

那么可能不是对象初始化吗?

LinqToSql生成的SQL是,等于==和Equals的。也是相同
Where(i => true).FirstOrDefault(i => i.ID == 2)


FirstOrDefault(i => i.ID == 2)

直到FirstOrDefault才有SQL查询,它会按预期正确构建查询。 where(i => true)仅继续在SQL查询中包含表达式构建和FirstOrDefault谓词。

我在 MSIL 的Reflector 中寻找的其他原因,但没有发现特别之处。

有猜到吗? :)

谢谢

#### Continuation(在.NET4.0中)

我设置了5种简单的方法来轻松检查反射器:
public void WithEquals(EntitiesDataContext ctx)
{
    ctx.GetTable<MyEntity>().FirstOrDefault(i => i.ID.Equals(2));
}

public void WithFakeWhereAndOperator(EntitiesDataContext ctx)
{
    ctx.GetTable<MyEntity>().Where(i => true).FirstOrDefault(i => i.ID == 2);
}

public void WithOperator(EntitiesDataContext ctx)
{
    ctx.GetTable<MyEntity>().FirstOrDefault(i => i.ID == 2);
}

public void WithOperatorSelect(EntitiesDataContext ctx)
{
    ctx.GetTable<MyEntity>().Where(i => i.ID == 2).Select(i => i).FirstOrDefault();
}

public void WithOperatorAndWhere(EntitiesDataContext ctx)
{
    ctx.GetTable<MyEntity>().Where(i => i.ID == 2).FirstOrDefault();
}

WithOperator和WithOperatorAndWhere失败,但是这是 MSIL 和我看到的内容:

WithOperator
  .method public hidebysig instance void WithOperator(class LinqToSqlTest.EntitiesDataContext ctx) cil managed
    {
        .maxstack 5
        .locals init (
            [0] class [System.Core]System.Linq.Expressions.ParameterExpression CS$0$0000,
            [1] class [System.Core]System.Linq.Expressions.ParameterExpression[] CS$0$0001)
        L_0000: nop 
        L_0001: ldarg.1 
        L_0002: callvirt instance class [System.Data.Linq]System.Data.Linq.Table`1<!!0> [System.Data.Linq]System.Data.Linq.DataContext::GetTable<class LinqToSqlTest.MyEntity>()
        L_0007: ldtoken LinqToSqlTest.MyEntity
        L_000c: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
        L_0011: ldstr "i"
        L_0016: call class [System.Core]System.Linq.Expressions.ParameterExpression [System.Core]System.Linq.Expressions.Expression::Parameter(class [mscorlib]System.Type, string)
        L_001b: stloc.0 
        L_001c: ldloc.0 
        L_001d: ldtoken instance int64 LinqToSqlTest.EntityBase::get_ID()
        L_0022: call class [mscorlib]System.Reflection.MethodBase [mscorlib]System.Reflection.MethodBase::GetMethodFromHandle(valuetype [mscorlib]System.RuntimeMethodHandle)
        L_0027: castclass [mscorlib]System.Reflection.MethodInfo
        L_002c: call class [System.Core]System.Linq.Expressions.MemberExpression [System.Core]System.Linq.Expressions.Expression::Property(class [System.Core]System.Linq.Expressions.Expression, class [mscorlib]System.Reflection.MethodInfo)
        L_0031: ldc.i4.2 
        L_0032: conv.i8 
        L_0033: box int64
        L_0038: ldtoken int64
        L_003d: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
        L_0042: call class [System.Core]System.Linq.Expressions.ConstantExpression [System.Core]System.Linq.Expressions.Expression::Constant(object, class [mscorlib]System.Type)
        L_0047: call class [System.Core]System.Linq.Expressions.BinaryExpression [System.Core]System.Linq.Expressions.Expression::Equal(class [System.Core]System.Linq.Expressions.Expression, class [System.Core]System.Linq.Expressions.Expression)
        L_004c: ldc.i4.1 
        L_004d: newarr [System.Core]System.Linq.Expressions.ParameterExpression
        L_0052: stloc.1 
        L_0053: ldloc.1 
        L_0054: ldc.i4.0 
        L_0055: ldloc.0 
        L_0056: stelem.ref 
        L_0057: ldloc.1 
        L_0058: call class [System.Core]System.Linq.Expressions.Expression`1<!!0> [System.Core]System.Linq.Expressions.Expression::Lambda<class [mscorlib]System.Func`2<class LinqToSqlTest.MyEntity, bool>>(class [System.Core]System.Linq.Expressions.Expression, class [System.Core]System.Linq.Expressions.ParameterExpression[])
        L_005d: call !!0 [System.Core]System.Linq.Queryable::FirstOrDefault<class LinqToSqlTest.MyEntity>(class [System.Core]System.Linq.IQueryable`1<!!0>, class [System.Core]System.Linq.Expressions.Expression`1<class [mscorlib]System.Func`2<!!0, bool>>)
        L_0062: pop 
        L_0063: ret 
    }

WithFakeWhereAndOperator
 .method public hidebysig instance void WithFakeWhereAndOperator(class LinqToSqlTest.EntitiesDataContext ctx) cil managed
    {
        .maxstack 5
        .locals init (
            [0] class [System.Core]System.Linq.Expressions.ParameterExpression CS$0$0000,
            [1] class [System.Core]System.Linq.Expressions.ParameterExpression[] CS$0$0001)
        L_0000: nop 
        L_0001: ldarg.1 
        L_0002: callvirt instance class [System.Data.Linq]System.Data.Linq.Table`1<!!0> [System.Data.Linq]System.Data.Linq.DataContext::GetTable<class LinqToSqlTest.MyEntity>()
        L_0007: ldtoken LinqToSqlTest.MyEntity
        L_000c: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
        L_0011: ldstr "i"
        L_0016: call class [System.Core]System.Linq.Expressions.ParameterExpression [System.Core]System.Linq.Expressions.Expression::Parameter(class [mscorlib]System.Type, string)
        L_001b: stloc.0 
        L_001c: ldc.i4.1 
        L_001d: box bool
        L_0022: ldtoken bool
        L_0027: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
        L_002c: call class [System.Core]System.Linq.Expressions.ConstantExpression [System.Core]System.Linq.Expressions.Expression::Constant(object, class [mscorlib]System.Type)
        L_0031: ldc.i4.1 
        L_0032: newarr [System.Core]System.Linq.Expressions.ParameterExpression
        L_0037: stloc.1 
        L_0038: ldloc.1 
        L_0039: ldc.i4.0 
        L_003a: ldloc.0 
        L_003b: stelem.ref 
        L_003c: ldloc.1 
        L_003d: call class [System.Core]System.Linq.Expressions.Expression`1<!!0> [System.Core]System.Linq.Expressions.Expression::Lambda<class [mscorlib]System.Func`2<class LinqToSqlTest.MyEntity, bool>>(class [System.Core]System.Linq.Expressions.Expression, class [System.Core]System.Linq.Expressions.ParameterExpression[])
        L_0042: call class [System.Core]System.Linq.IQueryable`1<!!0> [System.Core]System.Linq.Queryable::Where<class LinqToSqlTest.MyEntity>(class [System.Core]System.Linq.IQueryable`1<!!0>, class [System.Core]System.Linq.Expressions.Expression`1<class [mscorlib]System.Func`2<!!0, bool>>)
        L_0047: ldtoken LinqToSqlTest.MyEntity
        L_004c: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
        L_0051: ldstr "i"
        L_0056: call class [System.Core]System.Linq.Expressions.ParameterExpression [System.Core]System.Linq.Expressions.Expression::Parameter(class [mscorlib]System.Type, string)
        L_005b: stloc.0 
        L_005c: ldloc.0 
        L_005d: ldtoken instance int64 LinqToSqlTest.EntityBase::get_ID()
        L_0062: call class [mscorlib]System.Reflection.MethodBase [mscorlib]System.Reflection.MethodBase::GetMethodFromHandle(valuetype [mscorlib]System.RuntimeMethodHandle)
        L_0067: castclass [mscorlib]System.Reflection.MethodInfo
        L_006c: call class [System.Core]System.Linq.Expressions.MemberExpression [System.Core]System.Linq.Expressions.Expression::Property(class [System.Core]System.Linq.Expressions.Expression, class [mscorlib]System.Reflection.MethodInfo)
        L_0071: ldc.i4.2 
        L_0072: conv.i8 
        L_0073: box int64
        L_0078: ldtoken int64
        L_007d: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
        L_0082: call class [System.Core]System.Linq.Expressions.ConstantExpression [System.Core]System.Linq.Expressions.Expression::Constant(object, class [mscorlib]System.Type)
        L_0087: call class [System.Core]System.Linq.Expressions.BinaryExpression [System.Core]System.Linq.Expressions.Expression::Equal(class [System.Core]System.Linq.Expressions.Expression, class [System.Core]System.Linq.Expressions.Expression)
        L_008c: ldc.i4.1 
        L_008d: newarr [System.Core]System.Linq.Expressions.ParameterExpression
        L_0092: stloc.1 
        L_0093: ldloc.1 
        L_0094: ldc.i4.0 
        L_0095: ldloc.0 
        L_0096: stelem.ref 
        L_0097: ldloc.1 
        L_0098: call class [System.Core]System.Linq.Expressions.Expression`1<!!0> [System.Core]System.Linq.Expressions.Expression::Lambda<class [mscorlib]System.Func`2<class LinqToSqlTest.MyEntity, bool>>(class [System.Core]System.Linq.Expressions.Expression, class [System.Core]System.Linq.Expressions.ParameterExpression[])
        L_009d: call !!0 [System.Core]System.Linq.Queryable::FirstOrDefault<class LinqToSqlTest.MyEntity>(class [System.Core]System.Linq.IQueryable`1<!!0>, class [System.Core]System.Linq.Expressions.Expression`1<class [mscorlib]System.Func`2<!!0, bool>>)
        L_00a2: pop 
        L_00a3: ret 
    }

如我所见, FirstOrDefault 调用之间没有区别, WithFakeWhereAndOperator 只是“包括”关于Where语句的几行:

与等于
.method public hidebysig instance void WithEquals(class LinqToSqlTest.EntitiesDataContext ctx) cil managed
    {
        .maxstack 7
        .locals init (
            [0] class [System.Core]System.Linq.Expressions.ParameterExpression CS$0$0000,
            [1] class [System.Core]System.Linq.Expressions.Expression[] CS$0$0001,
            [2] class [System.Core]System.Linq.Expressions.ParameterExpression[] CS$0$0002)
        L_0000: nop 
        L_0001: ldarg.1 
        L_0002: callvirt instance class [System.Data.Linq]System.Data.Linq.Table`1<!!0> [System.Data.Linq]System.Data.Linq.DataContext::GetTable<class LinqToSqlTest.MyEntity>()
        L_0007: ldtoken LinqToSqlTest.MyEntity
        L_000c: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
        L_0011: ldstr "i"
        L_0016: call class [System.Core]System.Linq.Expressions.ParameterExpression [System.Core]System.Linq.Expressions.Expression::Parameter(class [mscorlib]System.Type, string)
        L_001b: stloc.0 
        L_001c: ldloc.0 
        L_001d: ldtoken instance int64 LinqToSqlTest.EntityBase::get_ID()
        L_0022: call class [mscorlib]System.Reflection.MethodBase [mscorlib]System.Reflection.MethodBase::GetMethodFromHandle(valuetype [mscorlib]System.RuntimeMethodHandle)
        L_0027: castclass [mscorlib]System.Reflection.MethodInfo
        L_002c: call class [System.Core]System.Linq.Expressions.MemberExpression [System.Core]System.Linq.Expressions.Expression::Property(class [System.Core]System.Linq.Expressions.Expression, class [mscorlib]System.Reflection.MethodInfo)
        L_0031: ldtoken instance bool [mscorlib]System.Int64::Equals(int64)
        L_0036: call class [mscorlib]System.Reflection.MethodBase [mscorlib]System.Reflection.MethodBase::GetMethodFromHandle(valuetype [mscorlib]System.RuntimeMethodHandle)
        L_003b: castclass [mscorlib]System.Reflection.MethodInfo
        L_0040: ldc.i4.1 
        L_0041: newarr [System.Core]System.Linq.Expressions.Expression
        L_0046: stloc.1 
        L_0047: ldloc.1 
        L_0048: ldc.i4.0 
        L_0049: ldc.i4.2 
        L_004a: conv.i8 
        L_004b: box int64
        L_0050: ldtoken int64
        L_0055: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
        L_005a: call class [System.Core]System.Linq.Expressions.ConstantExpression [System.Core]System.Linq.Expressions.Expression::Constant(object, class [mscorlib]System.Type)
        L_005f: stelem.ref 
        L_0060: ldloc.1 
        L_0061: call class [System.Core]System.Linq.Expressions.MethodCallExpression [System.Core]System.Linq.Expressions.Expression::Call(class [System.Core]System.Linq.Expressions.Expression, class [mscorlib]System.Reflection.MethodInfo, class [System.Core]System.Linq.Expressions.Expression[])
        L_0066: ldc.i4.1 
        L_0067: newarr [System.Core]System.Linq.Expressions.ParameterExpression
        L_006c: stloc.2 
        L_006d: ldloc.2 
        L_006e: ldc.i4.0 
        L_006f: ldloc.0 
        L_0070: stelem.ref 
        L_0071: ldloc.2 
        L_0072: call class [System.Core]System.Linq.Expressions.Expression`1<!!0> [System.Core]System.Linq.Expressions.Expression::Lambda<class [mscorlib]System.Func`2<class LinqToSqlTest.MyEntity, bool>>(class [System.Core]System.Linq.Expressions.Expression, class [System.Core]System.Linq.Expressions.ParameterExpression[])
        L_0077: call !!0 [System.Core]System.Linq.Queryable::FirstOrDefault<class LinqToSqlTest.MyEntity>(class [System.Core]System.Linq.IQueryable`1<!!0>, class [System.Core]System.Linq.Expressions.Expression`1<class [mscorlib]System.Func`2<!!0, bool>>)
        L_007c: pop 
        L_007d: ret 
    }

区别更大:

WithEquals 中,有一个额外的功能
[System.Core]System.Linq.Expressions.Expression[]

初始化,并在方法中间调用Equals。

此外,我可以看到 WithOperator 使用
call class [System.Core]System.Linq.Expressions.BinaryExpression [System.Core]System.Linq.Expressions.Expression::Equal(class [System.Core]System.Linq.Expressions.Expression, class [System.Core]System.Linq.Expressions.Expression)

WithEquals 使用
call class [System.Core]System.Linq.Expressions.MethodCallExpression [System.Core]System.Linq.Expressions.Expression::Call(class [System.Core]System.Linq.Expressions.Expression, class [mscorlib]System.Reflection.MethodInfo, class [System.Core]System.Linq.Expressions.Expression[])

这是第二张图片的第38行

嗯,也许是有关 BinaryExpression MethodCallExpression 之间的区别的问题?我将对此做进一步的研究。

这样的

我们有工作
public void WithOperatorSelect(EntitiesDataContext ctx)
{
    ctx.GetTable<MyEntity>().Where(i => i.ID == 2).Select(i => i).FirstOrDefault();
}

和...一样
public void WithOperatorAndWhere(EntitiesDataContext ctx)
{
    ctx.GetTable<MyEntity>().Where(i => i.ID == 2).FirstOrDefault();
}

但带有一个额外的伪造选择,它可用于

MSIL

WithOperatorAnd选择
.method public hidebysig instance void WithOperatorSelect(class LinqToSqlTest.EntitiesDataContext ctx) cil managed
    {
        .maxstack 5
        .locals init (
            [0] class [System.Core]System.Linq.Expressions.ParameterExpression CS$0$0000,
            [1] class [System.Core]System.Linq.Expressions.ParameterExpression[] CS$0$0001)
        L_0000: nop 
        L_0001: ldarg.1 
        L_0002: callvirt instance class [System.Data.Linq]System.Data.Linq.Table`1<!!0> [System.Data.Linq]System.Data.Linq.DataContext::GetTable<class LinqToSqlTest.MyEntity>()
        L_0007: ldtoken LinqToSqlTest.MyEntity
        L_000c: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
        L_0011: ldstr "i"
        L_0016: call class [System.Core]System.Linq.Expressions.ParameterExpression [System.Core]System.Linq.Expressions.Expression::Parameter(class [mscorlib]System.Type, string)
        L_001b: stloc.0 
        L_001c: ldloc.0 
        L_001d: ldtoken instance int64 LinqToSqlTest.EntityBase::get_ID()
        L_0022: call class [mscorlib]System.Reflection.MethodBase [mscorlib]System.Reflection.MethodBase::GetMethodFromHandle(valuetype [mscorlib]System.RuntimeMethodHandle)
        L_0027: castclass [mscorlib]System.Reflection.MethodInfo
        L_002c: call class [System.Core]System.Linq.Expressions.MemberExpression [System.Core]System.Linq.Expressions.Expression::Property(class [System.Core]System.Linq.Expressions.Expression, class [mscorlib]System.Reflection.MethodInfo)
        L_0031: ldc.i4.2 
        L_0032: conv.i8 
        L_0033: box int64
        L_0038: ldtoken int64
        L_003d: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
        L_0042: call class [System.Core]System.Linq.Expressions.ConstantExpression [System.Core]System.Linq.Expressions.Expression::Constant(object, class [mscorlib]System.Type)
        L_0047: call class [System.Core]System.Linq.Expressions.BinaryExpression [System.Core]System.Linq.Expressions.Expression::Equal(class [System.Core]System.Linq.Expressions.Expression, class [System.Core]System.Linq.Expressions.Expression)
        L_004c: ldc.i4.1 
        L_004d: newarr [System.Core]System.Linq.Expressions.ParameterExpression
        L_0052: stloc.1 
        L_0053: ldloc.1 
        L_0054: ldc.i4.0 
        L_0055: ldloc.0 
        L_0056: stelem.ref 
        L_0057: ldloc.1 
        L_0058: call class [System.Core]System.Linq.Expressions.Expression`1<!!0> [System.Core]System.Linq.Expressions.Expression::Lambda<class [mscorlib]System.Func`2<class LinqToSqlTest.MyEntity, bool>>(class [System.Core]System.Linq.Expressions.Expression, class [System.Core]System.Linq.Expressions.ParameterExpression[])
        L_005d: call class [System.Core]System.Linq.IQueryable`1<!!0> [System.Core]System.Linq.Queryable::Where<class LinqToSqlTest.MyEntity>(class [System.Core]System.Linq.IQueryable`1<!!0>, class [System.Core]System.Linq.Expressions.Expression`1<class [mscorlib]System.Func`2<!!0, bool>>)
        L_0062: ldtoken LinqToSqlTest.MyEntity
        L_0067: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
        L_006c: ldstr "i"
        L_0071: call class [System.Core]System.Linq.Expressions.ParameterExpression [System.Core]System.Linq.Expressions.Expression::Parameter(class [mscorlib]System.Type, string)
        L_0076: stloc.0 
        L_0077: ldloc.0 
        L_0078: ldc.i4.1 
        L_0079: newarr [System.Core]System.Linq.Expressions.ParameterExpression
        L_007e: stloc.1 
        L_007f: ldloc.1 
        L_0080: ldc.i4.0 
        L_0081: ldloc.0 
        L_0082: stelem.ref 
        L_0083: ldloc.1 
        L_0084: call class [System.Core]System.Linq.Expressions.Expression`1<!!0> [System.Core]System.Linq.Expressions.Expression::Lambda<class [mscorlib]System.Func`2<class LinqToSqlTest.MyEntity, class LinqToSqlTest.MyEntity>>(class [System.Core]System.Linq.Expressions.Expression, class [System.Core]System.Linq.Expressions.ParameterExpression[])
        L_0089: call class [System.Core]System.Linq.IQueryable`1<!!1> [System.Core]System.Linq.Queryable::Select<class LinqToSqlTest.MyEntity, class LinqToSqlTest.MyEntity>(class [System.Core]System.Linq.IQueryable`1<!!0>, class [System.Core]System.Linq.Expressions.Expression`1<class [mscorlib]System.Func`2<!!0, !!1>>)
        L_008e: call !!0 [System.Core]System.Linq.Queryable::FirstOrDefault<class LinqToSqlTest.MyEntity>(class [System.Core]System.Linq.IQueryable`1<!!0>)
        L_0093: pop 
        L_0094: ret 
    }

WithOperatorAndWhere
 .method public hidebysig instance void WithOperatorAndWhere(class LinqToSqlTest.EntitiesDataContext ctx) cil managed
    {
        .maxstack 5
        .locals init (
            [0] class [System.Core]System.Linq.Expressions.ParameterExpression CS$0$0000,
            [1] class [System.Core]System.Linq.Expressions.ParameterExpression[] CS$0$0001)
        L_0000: nop 
        L_0001: ldarg.1 
        L_0002: callvirt instance class [System.Data.Linq]System.Data.Linq.Table`1<!!0> [System.Data.Linq]System.Data.Linq.DataContext::GetTable<class LinqToSqlTest.MyEntity>()
        L_0007: ldtoken LinqToSqlTest.MyEntity
        L_000c: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
        L_0011: ldstr "i"
        L_0016: call class [System.Core]System.Linq.Expressions.ParameterExpression [System.Core]System.Linq.Expressions.Expression::Parameter(class [mscorlib]System.Type, string)
        L_001b: stloc.0 
        L_001c: ldloc.0 
        L_001d: ldtoken instance int64 LinqToSqlTest.EntityBase::get_ID()
        L_0022: call class [mscorlib]System.Reflection.MethodBase [mscorlib]System.Reflection.MethodBase::GetMethodFromHandle(valuetype [mscorlib]System.RuntimeMethodHandle)
        L_0027: castclass [mscorlib]System.Reflection.MethodInfo
        L_002c: call class [System.Core]System.Linq.Expressions.MemberExpression [System.Core]System.Linq.Expressions.Expression::Property(class [System.Core]System.Linq.Expressions.Expression, class [mscorlib]System.Reflection.MethodInfo)
        L_0031: ldc.i4.2 
        L_0032: conv.i8 
        L_0033: box int64
        L_0038: ldtoken int64
        L_003d: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
        L_0042: call class [System.Core]System.Linq.Expressions.ConstantExpression [System.Core]System.Linq.Expressions.Expression::Constant(object, class [mscorlib]System.Type)
        L_0047: call class [System.Core]System.Linq.Expressions.BinaryExpression [System.Core]System.Linq.Expressions.Expression::Equal(class [System.Core]System.Linq.Expressions.Expression, class [System.Core]System.Linq.Expressions.Expression)
        L_004c: ldc.i4.1 
        L_004d: newarr [System.Core]System.Linq.Expressions.ParameterExpression
        L_0052: stloc.1 
        L_0053: ldloc.1 
        L_0054: ldc.i4.0 
        L_0055: ldloc.0 
        L_0056: stelem.ref 
        L_0057: ldloc.1 
        L_0058: call class [System.Core]System.Linq.Expressions.Expression`1<!!0> [System.Core]System.Linq.Expressions.Expression::Lambda<class [mscorlib]System.Func`2<class LinqToSqlTest.MyEntity, bool>>(class [System.Core]System.Linq.Expressions.Expression, class [System.Core]System.Linq.Expressions.ParameterExpression[])
        L_005d: call class [System.Core]System.Linq.IQueryable`1<!!0> [System.Core]System.Linq.Queryable::Where<class LinqToSqlTest.MyEntity>(class [System.Core]System.Linq.IQueryable`1<!!0>, class [System.Core]System.Linq.Expressions.Expression`1<class [mscorlib]System.Func`2<!!0, bool>>)
        L_0062: call !!0 [System.Core]System.Linq.Queryable::FirstOrDefault<class LinqToSqlTest.MyEntity>(class [System.Core]System.Linq.IQueryable`1<!!0>)
        L_0067: pop 
        L_0068: ret 
    }

和区别:

唯一的区别(除了WithOperatorAndSelect的工作:)之外)是MSIL中的Select语句。

所以我想这不是==运算符/等于问题。但是我不知道。

最佳答案

好的,这似乎是一个已知的错误:

http://connect.microsoft.com/VisualStudio/feedback/details/394255/linq-to-sql-bug-handling-entities-with-common-base-class

它不会被修复。

相关问题:

LINQ to SQL - mapping exception when using abstract base classes

LinqToSql and abstract base classes

无论如何,谢谢弗兰克·坦那贝提斯(Frank Tzanabetis)的努力。

关于c# - 有趣的Linq to SQL通用基类行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7673246/

相关文章:

c# - 在Linq-to-SQL插入过程中,自增主键值什么时候可用?

c# - "final"在 IL 中是什么意思?

inheritance - Mono.Cecil:从其他程序集调用基类的方法

c# - 处理 RedirectStandardOutput 为空且 DataReceivedEventArgs.Data 为空

c# - 谁能帮我解释一下这些方法的时间安排?

c# - 如何将方程式转换为单个变量的公式?

c# - GroupJoin 和包含

c# - LINQ to SQL 比较性能

C# EMIT IL 性能问题

c# - 为什么在 .Net 4.7.2 项目中引用 .Net 标准 nuget 包会导入大量 .Net core lib?