Linq Queries Serialization: вариант реализации

суббота, 2 июня 2012, Александр Краковецкий

Возникла как-то одна интересная задача: получать уникальный идентификатор (число или строка - не важно) для уникальных LINQ выражений, включая значения переменных.

Например, выражения:

from i in obj
where i.Property == "value1"
select i;

from i in obj
where i.Property == "value1"
select new { i.Property };

from i in obj
where i.Property == "value2"
select new { i.Property };

должны выдавать разные идентификаторы.

На первый взгляд, задача простая - есть expression trees, с их помощью легко распарсить выражения и получить уникальный идентификатор, но тем не менее пришлось немного поиграться.

После многих попыток получилось задачу частично решить (частично, потому как не доказано, что будет работать верно для всех возможных вариантов).

Тестовый пример выглядит таким образом:

namespace LinqQueriesSerialization
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using ExpressionSerialization;

    class Program
    {
        static readonly List<Customer> Object = new List<Customer> 
            { 
                new Customer { CustomerID = "1", Fax = "111111", City = "London", CompanyName ="Company Name" }
            };

        static void Main(string[] args)
        {
            Console.WriteLine(GetByValue1());
            Console.WriteLine(GetByValue1("New York"));
            Console.WriteLine(GetByValue1("New York", "333333"));
            Console.WriteLine(GetByValue2());
            Console.WriteLine(GetByValue2("New York"));
            Console.WriteLine(GetByValue2("New York", "333333"));

            Console.ReadLine();
        }

        private static string GetByValue1(string city = "London", string fax = "222222")
        {
            var query = from c in Object.AsQueryable()
                        where c.City == city && c.Fax != fax
                        select new { c.CompanyName };

            return new QuerySerializationManager().GetKey(query);
        }

        private static string GetByValue2(string city = "London", string fax = "222222")
        {
            var query = from c in Object.AsQueryable()
                        where c.City == city && c.Fax == fax
                        select new { c.CompanyName };

            return new QuerySerializationManager().GetKey(query);
        }
    }
}

Если запустить этот пример, то получим:

TdnxbC4Jmm5x2dQAq/Z5LQ==
gQx3jvWCUoROaD0KAopOug==
vGsMQfbVMEkUsV08kwnV2A==
Qig0QbqaVEoj2kTSnTMjLA==
hOK0qEyqu8oRbSmTN1tZSQ==
ox28abchtbN8C6ikCfU5Zg==

Т.е. то, что нам нужно.

Внутри QuerySerializationManager спрятано много функционала - из проекта Expression Tree Serialization + допиливание.

Скачать исходники можно по ссылке ниже:

Если есть другие способы решения подобной задачи - поделитесь.


Ищите нас в интернетах!

Комментарии

Свежие вакансии