gpt4 book ai didi

c# - 有什么方法可以在 L2S 身份映射中查找项目?

转载 作者:太空狗 更新时间:2023-10-29 19:39:56 25 4
gpt4 key购买 nike

LINQ-2-SQL 维护一个标识映射,因此对 entity.First(e => e.Id == id) 的后续调用不会导致超出第一个上下文的其他查询。

有没有办法询问 L2S 身份映射中是否存在特定项目?

我问这个原因是因为支持 .Attach 允许您将实体附加到上下文,但是如果该项目已经存在于身份映射中,该方法将异常。

在互操作性场景中,我可能希望以不同的、更快的 orm 加载实体并附加,但是如果实体已经在身份映射中,则查找它是没有意义的。

最佳答案

没有什么好办法……不过你可以黑进去。例如,假设您有一个 User 对象,您知道该对象由 Id 键控:

var user = // get some user
var dataContext = // your DB context

const BindingFlags AllInstance = BindingFlags.Instance | BindingFlags.NonPublic
| BindingFlags.Public;
object commonDataServices = typeof(DataContext)
.GetField("services", AllInstance)
.GetValue(dataContext);
object identifier = commonDataServices.GetType()
.GetProperty("IdentityManager", AllInstance)
.GetValue(commonDataServices, null);
MethodInfo find = identifier.GetType().GetMethod("Find", AllInstance);
var metaType = dataContext.Mapping.GetMetaType(typeof(User));
object[] keys = new object[] { user.Id };
var user2 = (User)find.Invoke(identifier, new object[] { metaType, keys });
bool pass = ReferenceEquals(user, user2);

几乎所有访问都是非公开的;我预计这会降低性能,除非您使用 DynamicMethod 欺骗其他类型的访问。

作为 DynamicMethod 版本:

(是的,我正在对 int 键进行硬编码...您可以通过将 int 替换为 object 来使其成为任何单值,然后删除 OpCodes.Box, typeof(int) - 或者您可以将其设为 params object[] 参数并直接传入)

static readonly Func<DataContext, Type, int, object> identityLookup = BuildIdentityLookup();

static Func<DataContext, Type, int, object> BuildIdentityLookup()
{
var quickFind = new DynamicMethod("QuickFind", typeof(object), new Type[] { typeof(DataContext), typeof(Type), typeof(int) }, typeof(DataContext), true);
var il = quickFind.GetILGenerator();

const BindingFlags AllInstance = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
il.Emit(OpCodes.Ldarg_0); // DB
var services = typeof(DataContext).GetField("services", AllInstance);
il.Emit(OpCodes.Ldfld, services); // services

var identifier = services.FieldType.GetProperty("IdentityManager", AllInstance);
il.EmitCall(OpCodes.Callvirt, identifier.GetGetMethod(true), null); // identifier

il.Emit(OpCodes.Ldarg_0); // identifier DB
var mapping = typeof(DataContext).GetProperty("Mapping");
il.EmitCall(OpCodes.Callvirt, mapping.GetGetMethod(), null); // identifier mapping

il.Emit(OpCodes.Ldarg_1); // identifier mapping type
il.EmitCall(OpCodes.Callvirt, mapping.PropertyType.GetMethod("GetMetaType"), null); // identifier metatype

il.Emit(OpCodes.Ldc_I4_1); // identifier metatype 1
il.Emit(OpCodes.Newarr, typeof(object)); // identifier metatype object[]
il.Emit(OpCodes.Dup); // identifier metatype object[] object[]
il.Emit(OpCodes.Ldc_I4_0); // identifier metatype object[] object[] 0
il.Emit(OpCodes.Ldarg_2); // identifier metatype object[] object[] 0 id
il.Emit(OpCodes.Box, typeof(int)); // identifier metatype object[] object[] 0 boxed-id
il.Emit(OpCodes.Stelem_Ref); // identifier metatype object[]

il.EmitCall(OpCodes.Callvirt, identifier.PropertyType.GetMethod("Find", AllInstance), null); // object
il.Emit(OpCodes.Ret);

return (Func<DataContext, Type, int, object>)quickFind.CreateDelegate(typeof(Func<DataContext, Type, int, object>));
}

关于c# - 有什么方法可以在 L2S 身份映射中查找项目?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6171558/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com