この文書クラスが与えられた場合:
public class Product
{
public string Id { get; set; }
public string Name { get; set; }
public SpecialType? DefaultOffer { get; set; }
public Dictionary<SpecialType, string> Specials { get; set; }
}
public enum SpecialType
{
Something1,
Something2
}
そして、上記のドキュメントから投影したいこのビューモデル:
public class ProductSummary
{
public string Id { get; set; }
public string Name { get; set; }
public string SpecialOffer { get; set; }
}
次のインデックスを作成しました。
public class ProductSummaries : AbstractIndexCreationTask<Product>
{
public ProductSummaries()
{
Map = products => from p in products
select new { p.Id, p.Name, p.DefaultOffer, p.Specials };
TransformResults = (db, products) =>
from p in products
select new
{
Id = p.Id,
Name = p.Name,
SpecialOffer = p.Specials[p.DefaultOffer.Value]
};
}
}
簡単に言えば、Specials
現在の の値によって示されるディクショナリ内の文字列のいずれかをビュー モデルで使用する必要がありDefaultOffer
ます。
次の単体テストは失敗します。
[TestMethod]
public void CanIndexIntoDictionary()
{
using (var documentStore = this.GetDocumentStore())
{
documentStore.ExecuteIndex(new ProductSummaries());
// Store some documents
using (var session = documentStore.OpenSession())
{
session.Store(new Product
{
Id = "products/2",
Name = "B",
Specials = new Dictionary<SpecialType, string>
{
{ SpecialType.Something1, "B1" },
{ SpecialType.Something2, "B2" }
},
DefaultOffer = SpecialType.Something2
});
session.SaveChanges();
}
// Make sure it got persisted correctly
using (var session = documentStore.OpenSession())
{
var b = session.Load<Product>("products/2");
Assert.AreEqual("B2", b.Specials[b.DefaultOffer.Value]); // PASSES
}
// Now query and transform
using (var session = documentStore.OpenSession())
{
var result = session.Query<Product, ProductSummaries>()
.Customize(x => x.WaitForNonStaleResults())
.AsProjection<ProductSummary>()
.ToList();
Assert.AreEqual(1, result.Count);
Assert.AreEqual("B2", result.First().SpecialOffer); // FAILS - actual is NULL
}
}
}
このテストに合格するにはどうすればよいですか?
* アップデート *
NONE を表す Enum 値を持つというマットの提案 (以下のコメント) を使用することで、彼の答えを変更し、null 許容列挙型を取り除くことができます。モデル全体とインデックスがよりきれいに見えます。
public enum SpecialType
{
None = 0,
Something1,
Something2
}
public class Product
{
public string Id { get; set; }
public string Name { get; set; }
public SpecialType DefaultOffer { get; set; }
public Dictionary<SpecialType, string> Specials { get; set; }
}
public class ProductSummaries : AbstractIndexCreationTask<Product,ProductSummary>
{
public ProductSummaries()
{
Map = products => from p in products
select new { p.Name, SpecialOffer = p.Specials[p.DefaultOffer] };
Store(x => x.SpecialOffer, FieldStorage.Yes);
}
}
興味深いことに、このインデックスを使用すると、null チェックなどの必要がなくなります。RavenDBは、キーがディクショナリに含まれていないSpecialOffer
場合に null に設定するだけだからです。(これは、p.Name がマップに含まれている場合にのみ当てはまります。)p.DefaultOffer
Specials