2015-11-15 3 views
0

Итак, я пытаюсь использовать DocumentDB для хранения некоторых объектов, которые содержат список дочерних компонентов, которые могут быть разных типов. Простой пример того, что я хочу, чтобы хранить следующим образом:Как читать массив производных объектов из DocumentDB с .NET-клиентом

public class Component 
{ 
    public string ComponentType { get; set; } 
} 

public class BudgetComponent: Component 
{ 
    public decimal Budget { get; set; } 
} 

public class DateRangeComponent: Component 
{ 
    public DateTime Start { get; set; } 
    public DateTime End { get; set; } 
} 

public class Entity 
{ 
    public IEnumerable<Component> Components { get; set; } 
} 

Это позволит сэкономить правильно, но когда я пытаюсь читать я столкнуться с проблемами. Если бы я это сделать:

var docs = Client.CreateDocumentQuery<Entity>(Collection.DocumentsLink); 

тогда я в конечном итоге с классом сущностей с перечнем Component объектов; не BudgetComponent/DateRangeComponent объектов.

Это имеет смысл, поскольку БД не хранит информацию о фактическом типе. Я бы предположил, что это довольно распространенный сценарий, поэтому я надеюсь, что есть решение.

Одна вещь, которую я пробовал, заключается в том, чтобы использовать неосновный вызов CreateDocumentQuery для возврата объекта Document и вручную де-сериализовать свойства. Есть 2 проблемы с подходом, который я использовал:

1) Кажется, мне нужно собрать коллекцию компонентов в виде коллекции объектов dynamic, которая теряет безопасность типа, intellisense и т. Д. ... и быстро получит бесполезно, если у Компонентов есть собственные дети.

2) Возможно, более существенно, я теряю возможность использовать Linq для строго типизированных запросов против Entity.

Итак, есть ли элегантное решение этой проблемы с DocumentDB?

+0

Извините, что связано с LINQ? Это полностью агностично для хранилища, даже если нет жесткого хранилища (только объекты памяти). Вы имели в виду [tag: entity-framework]? Если да, взгляните на [Реализация наследования (EF)] (http://www.asp.net/mvc/overview/getting-started/getting-started-with-ef-using-mvc/implementing-inheritance-with- заместитель сущность-рамки-в-в-Asp-нетто-MVC-приложения). –

+0

Я имею в виду клиента DocumentDB .NET, который разрешает запросы Linq, которые преобразуются в запросы базы данных (аналогично Linq to Entities в EF). т.е. 'CreateDocumentQuery (Collection.DocumentsLink) .Where (e => e.Tenant ==" vds ");' Я не могу этого сделать, если я использую не-общую версию 'CreateDocumentQuery', насколько это возможно Я могу сказать. – Gerald

ответ

0

Если ваша коллекция имеет смешанные типы, то это не сработает, потому что нет информации о типе, хранящейся (как вы правильно указали выше). Однако, если ваши коллекции содержат отдельные типы в каждой коллекции, и вы точно знаете тип, который вы извлекаете, это может вам помочь.

Сначала нужно создать хранилище, которое принимает обобщенный тип и имеет статический метод, который принимает ссылку коллекции документа в виде строки:

public class DocumentRepository<T> where T : class 
    {    
     public static IEnumerable<T> GetDocuments(string docLink) 
     { 
      //code assumes Client object is instantiated earlier 
      var docs = Client.CreateDocumentQuery<T>(docLink).AsEnumerable(); 

      return docs; 
     } 
    } 

Тогда вы можете вызвать его из кода, как это:

var docs= DocumentRepository<DateRangeComponent> 
          .GetDocuments(Collection.DocumentsLink); 

Примечание: вызов в .AsEnumerable() в репозитории ленив и не будет выполняться до тех пор, пока вы не перечислите коллекцию. Опция .AsEnumerable() также является необязательной, и вызов CreateDocumentQuery вместо этого возвращает коллекцию IOrderedQueryable, которая также будет исполнять ленивый. Вы можете поочередно использовать .ToList(), чтобы выполнить его раньше. Множество вариантов!

Надеюсь, это поможет.

+0

Мне нужно, чтобы это была единственная коллекция типов Entity, и каждый Entity содержит встроенный список смешанных типов. Это то, что, по-видимому, находится на их радаре, но они не ожидают его реализовать в ближайшее время. Таким образом, я закончил тем, что отказался от DocumentDB и вместо этого использовал MongoDB в наборе виртуальных машин. В .NET-библиотеке Mongo есть встроенная поддержка для настройки карт классов с дискриминаторами для достижения такого рода вещей. Я все еще теряю возможность использовать Linq для создания запросов, но в любом случае это оказалось иначе в DocDB, и по крайней мере мне не нужно иметь дело с объектами 'dynamic'. – Gerald

Смежные вопросы