Ответ 1
Использовать денормализованные ссылки:
http://ravendb.net/faq/denormalized-references
по существу у вас есть класс DenormalizedReference:
public class DenormalizedReference<T> where T : INamedDocument
{
public string Id { get; set; }
public string Name { get; set; }
public static implicit operator DenormalizedReference<T> (T doc)
{
return new DenormalizedReference<T>
{
Id = doc.Id,
Name = doc.Name
}
}
}
ваши документы выглядят так: я реализовал интерфейс INamedDocument - это может быть все, что вам нужно, но:
public class Company : INamedDocument
{
public string Name{get;set;}
public int Id { get; set; }
public IList<DenormalizedReference<Contact>> Contacts { get; set; }
public IList<DenormalizedReference<Task>> Tasks { get; set; }
}
public class Contact : INamedDocument
{
public string Name{get;set;}
public int Id { get; set; }
public DenormalizedReference<Company> Company { get; set; }
public IList<DenormalizedReference<Task>> Tasks { get; set; }
}
public class Task : INamedDocument
{
public string Name{get;set;}
public int Id { get; set; }
public DenormalizedReference<Company> Company { get; set; }
public DenormalizedReference<Contact> Contact { get; set; }
}
Теперь сохранение задачи работает так же, как и раньше:
var task = new Task{
Company = myCompany,
Contact = myContact
};
Однако вытащить все это будет означать, что вы только получите денормализованную ссылку для дочерних объектов. Для гидратации они используют индекс:
public class Tasks_Hydrated : AbstractIndexCreationTask<Task>
{
public Tasks_Hydrated()
{
Map = docs => from doc in docs
select new
{
doc.Name
};
TransformResults = (db, docs) => from doc in docs
let Company = db.Load<Company>(doc.Company.Id)
let Contact = db.Load<Contact>(doc.Contact.Id)
select new
{
Contact,
Company,
doc.Id,
doc.Name
};
}
}
И используя ваш индекс для извлечения увлажненных задач:
var tasks = from c in _session.Query<Projections.Task, Tasks_Hydrated>()
where c.Name == "taskmaster"
select c;
Что я считаю довольно чистым:)
В качестве дизайнерского разговора - общее правило заключается в том, что если вам когда-либо понадобится загружать дочерние документы самостоятельно, как в - не часть родительского документа. Будь то для редактирования или просмотра - вы должны моделировать его своим собственным Id как собственным документом. Использование вышеописанного метода делает это довольно простым.