Есть ли способ найти предмет на карте идентификации L2S? - PullRequest
8 голосов
/ 30 мая 2011

LINQ-2-SQL поддерживает карту идентификаторов, поэтому последующие вызовы entity.First(e => e.Id == id) не вызывают дополнительных запросов для контекста, кроме первого запроса.

Есть ли возможность спросить L2S, существует ли конкретный элемент вкарта личности?

Я спрашиваю, потому что существует поддержка .Attach, которая позволяет вам присоединять сущности к контексту, однако метод будет исключать, если элемент уже существует в карте удостоверений.

ВВ сценарии взаимодействия я могу захотеть загрузить объекты в другом, более быстром режиме и присоединить, однако нет смысла искать объект, если он уже находится в карте идентификаторов.

1 Ответ

6 голосов
/ 30 мая 2011

Нет хорошего способа ... вы можете взломать свой путь, хотя. Например, представьте, что у вас есть 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>));
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...