以下是给定的类:
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
};
}
}
这种方法可以达到预期效果,将数据转换为客户端应用所需的结构形式。然而,这种方式过于冗长,维护起来非常困难,构建冗余对象的效率可能也不高。 是否有更简单的方法,可以在给定文档集(DocA)的情况下创建具有所需结构(ViewA)的索引呢? 更多信息: 问题似乎在于为了让索引按照转换后的结构(ViewA)保存数据,我们必须进行Reduce操作。Reduce必须包含GROUP ON和SELECT才能按预期工作,所以下面两种写法无效:
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必须具有带有对象创建表达式的lambda表达式。
显然,我们需要使用 'select new'。
无效的REDUCE子句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'。
显然,我们还需要在“group on new”上进行处理。
感谢您所提供的任何帮助。
(注意:从构造函数调用中删除类型(ViewA)对上述内容没有影响)
使用正确方法更新
如下面答案中提到的Daniel的博客所概述的,这是此示例的正确方法:
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);
}
}