Учитывая следующие классы:
public class Lookup
{
public string Code { get; set; }
public string Name { get; set; }
}
public class DocA
{
public string Id { get; set; }
public string Name { get; set; }
public Lookup Currency { get; set; }
}
public class ViewA // Simply a flattened version of the doc
{
public string Id { get; set; }
public string Name { get; set; }
public string CurrencyName { get; set; } // View just gets the name of the currency
}
Я могу создать индекс, который позволяет клиенту запрашивать представление следующим образом:
public class A_View : AbstractIndexCreationTask<DocA, ViewA>
{
public A_View()
{
Map = docs => from doc in docs
select new ViewA
{
Id = doc.Id,
Name = doc.Name,
CurrencyName = doc.Currency.Name
};
Reduce = results => from result in results
group on new ViewA
{
Id = result.Id,
Name = result.Name,
CurrencyName = result.CurrencyName
} into g
select new ViewA
{
Id = g.Key.Id,
Name = g.Key.Name,
CurrencyName = g.Key.CurrencyName
};
}
}
Это, безусловно, работает и дает желаемый результатпредставление с данными, преобразованными в структуру, требуемую в клиентском приложении.Тем не менее, это неоправданно многословно, будет кошмаром обслуживания и, вероятно, довольно неэффективно со всей избыточной конструкции объекта.
Существует ли более простой способ создания индекса с требуемой структурой (ViewA) для данной коллекции документов (DocA)?
ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ Проблема заключается в том, что для того, чтобы индекс содержал данные в преобразованной структуре (ViewA), мы должны сделать Reduce.Похоже, что Reduce должен иметь как GROUP ON, так и SELECT, чтобы работать должным образом, поэтому следующее недопустимо:
НЕПРАВИЛЬНОЕ СНИЖЕНИЕ КЛАУЗ 1:
Reduce = results => from result in results
group on new ViewA
{
Id = result.Id,
Name = result.Name,
CurrencyName = result.CurrencyName
} into g
select g.Key;
Это приводит к: System.InvalidOperationException: инициализатор переменной select должен иметь лямбда-выражение с выражением создания объекта
Ясно, что нам нужно иметь 'select new'.
INVALIDУМЕНЬШЕНИЕ ОБЪЕКТА 2:
Reduce = results => from result in results
select new ViewA
{
Id = result.Id,
Name = result.Name,
CurrencyName = result.CurrencyName
};
Это приводит к: System.InvalidCastException: Невозможно привести объект типа 'ICSharpCode.NRefactory.Ast.IdentifierExpression' к типу ICSharpCode.NRefactory.Ast.InvocationExpression.
Понятно, что нам также нужно иметь «группу новых».
Спасибо за любую помощь, которую вы можете предоставить.
(Примечание: удаление типа (ViewA) извызовы конструктора не влияют на вышесказанное)
ОБНОВЛЕНИЕ С ПРАВИЛЬНЫМ ПОДХОДОМ
Как указано в блоге Дэниела, упомянутом в ответе ниже, вот правильный способ сделатьэто для этого примера:
public class A_View : AbstractIndexCreationTask<DocA, ViewA>
{
public A_View()
{
Map = docs => from doc in docs
select new ViewA
{
Id = doc.Id,
Name = doc.Name,
CurrencyName = doc.Currency.Name
};
// Top-level properties on ViewA that match those on DocA
// do not need to be stored in the index.
Store(x => x.CurrencyName, FieldStorage.Yes);
}
}