Id上重用索引转换器表达式失败

时间:2013-01-15 07:56:07

标签: c# linq ravendb

我希望能够从索引中重用一些转换表达式,这样当文档可用时我可以在服务层中执行相同的转换。

例如,无论是通过查询还是通过转换服务层的现有文档,我都希望生成具有以下形状的ViewModel对象:

public class ClientBrief
{
    public int Id { get; set; }
    public string FullName { get; set; }
    public string Email { get; set; }
    // ellided
}

从这个文档模型:

public class Client
{
    public int Id { get; private set; }
    public CompleteName Name { get; private set; }
    public Dictionary<EmailAddressKey, EmailAddress> Emails { get; private set; }
    // ellided
}

public class CompleteName
{
    public string Title { get; set; }
    public string GivenName { get; set; }
    public string MiddleName { get; set; }
    public string Initials { get; set; }
    public string Surname { get; set; }
    public string Suffix { get; set; }
    public string FullName { get; set; }
}

public enum EmailAddressKey
{
    EmailAddress1,
    EmailAddress2,
    EmailAddress3
}

public class EmailAddress
{
    public string Address { get; set; }
    public string Name { get; set; }
    public string RoutingType { get; set; }
}

我有一个表达式可以将完整的客户端文档转换为ClientBrief视图模型:

    static Expression<Func<IClientSideDatabase, Client, ClientBrief>> ClientBrief = (db, client) =>
        new ClientBrief
        {
            Id = client.Id,
            FullName = client.Name.FullName,
            Email = client.Emails.Select(x => x.Value.Address).FirstOrDefault()
            // ellided
        };

然后使用表达式访问者操作此表达式,以便它可以用作索引(Client_Search)的TransformResults属性,该索引在应用程序启动时生成后,在Raven Studio中具有以下定义:

地图:

docs.Clients.Select(client => new {
    Query = new object[] {
        client.Name.FullName,
        client.Emails.SelectMany(x => x.Value.Address.Split(new char[] {
            '@'
        })) // ellided
    }
})

(分析Query字段。)

变换:

results.Select(result => new {
    result = result,
    client = Database.Load(result.Id.ToString())
}).Select(this0 => new {
    Id = this0.client.__document_id,
    FullName = this0.client.Name.FullName,
    Email = DynamicEnumerable.FirstOrDefault(this0.client.Emails.Select(x => x.Value.Address))
})

但是,当我已经拥有客户端文档时,用于创建索引的转换表达式也可以在本地服务层中使用:

var brief = ClientBrief.Compile().Invoke(null, client);

它允许我只需拥有一段能够理解从Client到ClientBrief的映射的代码,无论该代码是在数据库还是客户端应用程序中运行。这一切似乎都运行正常,但查询结果的ID均为0

如何在查询中正确填充Id属性(整数)?

我在这里已经阅读了许多类似的问题,但没有一个建议的答案似乎有效。 (将ID从整数更改为字符串不是一种选择。)

1 个答案:

答案 0 :(得分:0)

我很难完全跟踪你的样本,真正最好的方法是使用失败的自包含单元测试。

尽管如此,让我们看看能否取出重要的一些内容。

在转换中,您有两个使用id的区域:

...
client = Database.Load(result.Id.ToString())
...
Id = this0.client.__document_id,
...

第一行中的result.Id和第二行中的Id =应为整数。

Database.Load()需要一个字符串文档密钥,这也是您在__document_id中看到的内容。

Raven的文档,代码和示例的混淆都是可以互换地使用术语 id key ,但这只是 时才是真的你使用字符串标识符。当您使用非字符串标识符(例如int或guid)时, id 可能为123,但文档密钥仍为clients/123

因此,请尝试更改转换,以便进行翻译:

...
client = Database.Load("clients/" + result.Id)
...
Id = int.Parse(this0.client.__document_id.Split("/")[1]),
...

......或者c#等效的linq形式。