2017-01-09 29 views
1

我接近文件數據庫和我有點困惑如何映射文件的關係,在一個情況如下型號一對多在RavenDb有更好的表現

public class Person 
{ 
    public Person() 
    { 
    } 
    public int Id { get; set; } 
    public string Name { get;set;} 
    public string Surname { get; set; } 
    public DateTime? BirthDate { get; set; } 
} 


public class Car 
{ 
    public Car() { } 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public int PersonId { get; set;} 
} 

每人都有一個或多個汽車爲例這樣我可以查詢數據庫作爲跟隨

public Car Get(int id) 
    { 
     Car car = null; 
     using (IDocumentSession session = store.OpenSession()) 
     { 
      car = session.Include<Car, Person>(x => x.PersonId).Load<Car>(id); 
      bool isLoaded = session.Advanced.IsLoaded("people/" + car.PersonId); // true! 
     } 
     return car; 
    } 

,它的一切就OK了,客戶端會只是一個請求,但如果我有一個人,我想告訴他所有的車我該怎麼查詢數據庫只做一個請求? 我認爲我必須修改模型,將List<int> Cars放入Person以供參考。 請注意,我不想在Person文檔中嵌入Cars,因爲Cars可以從其他文檔引用。

感謝。

回答

3

您可以索引Cars集合並從索引中加載所有的汽車。

的指數應該是這樣的:

public class CarIndex : AbstractIndexCreationTask<Car, CarView> 
{ 
    public CarIndex() 
    { 
     Map = cars => from car in cars 
         select new 
         { 
          car.Id, 
          car.Name, 
          car.PersonId, 
         }; 
    } 
} 

的Carview會類是相同的轎車類,但可以改變以更好地適應索引的需要。

public class CarView 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public int PersonId { get; set; } 
} 

你需要能夠使用它之前執行索引:

new CarIndex().Execute(store); 

裝載汽車的某個人是這樣的:

using (IDocumentSession session = store.OpenSession()) 
{ 
    session.Store(new Person { Id = 1, Name = "A", Surname = "A" }); 
    session.Store(new Car { Id = 1, Name = "A", PersonId = 1 }); 
    session.Store(new Car { Id = 2, Name = "B", PersonId = 1 }); 
    session.Store(new Car { Id = 3, Name = "C", PersonId = 2 }); 
    session.SaveChanges(); 
} 

WaitForIndexing(store); // from RavenTestBase 

using (IDocumentSession session = store.OpenSession()) 
{ 
    var resultsForId1 = session 
     .Query<CarView, CarIndex>() 
     .ProjectFromIndexFieldsInto<CarView>() 
     .Where(x => x.PersonId == 1); 
    Assert.Equal(2, resultsForId1.Count()); 
    var resultsForId2 = session 
     .Query<CarView, CarIndex>() 
     .ProjectFromIndexFieldsInto<CarView>() 
     .Where(x => x.PersonId == 2); 
    Assert.Equal(1, resultsForId2.Count()); 
} 

如果您想要在單個數據庫請求中加載人員和他們的汽車,請使用延遲加載:

var resultsForId1 = session 
    .Query<CarView, CarIndex>() 
    .ProjectFromIndexFieldsInto<CarView>() 
    .Where(x => x.PersonId == 1).Lazily(); 
var person = session.Advanced.Lazily.Load<Person>(1); 

var personValue = person.Value; 
var resultsValue = resultsForId1.Value; 

完整的測試(需要的xUnit和RavenDB.Tests.Helpers nugets):

using Raven.Client; 
using Raven.Client.Indexes; 
using Raven.Tests.Helpers; 
using System; 
using System.Linq; 
using Xunit; 

namespace SO41547501Answer 
{ 
    public class SO41547501 : RavenTestBase 
    { 
     [Fact] 
     public void SO41547501Test() 
     { 
      using (var server = GetNewServer()) 
      using (var store = NewRemoteDocumentStore(ravenDbServer: server)) 
      { 
       new CarIndex().Execute(store); 

       using (IDocumentSession session = store.OpenSession()) 
       { 
        session.Store(new Person { Id = 1, Name = "A", Surname = "A" }); 
        session.Store(new Car { Id = 1, Name = "A", PersonId = 1 }); 
        session.Store(new Car { Id = 2, Name = "B", PersonId = 1 }); 
        session.Store(new Car { Id = 3, Name = "C", PersonId = 2 }); 
        session.SaveChanges(); 
       } 

       WaitForAllRequestsToComplete(server); 
       WaitForIndexing(store); 

       using (IDocumentSession session = store.OpenSession()) 
       { 
        var resultsForId1 = session 
         .Query<CarView, CarIndex>() 
         .ProjectFromIndexFieldsInto<CarView>() 
         .Where(x => x.PersonId == 1); 
        Assert.Equal(2, resultsForId1.Count()); 
        var resultsForId2 = session 
         .Query<CarView, CarIndex>() 
         .ProjectFromIndexFieldsInto<CarView>() 
         .Where(x => x.PersonId == 2); 
        Assert.Equal(1, resultsForId2.Count()); 
       } 

       using (IDocumentSession session = store.OpenSession()) 
       { 
        server.Server.ResetNumberOfRequests(); 
        var resultsForId1 = session 
         .Query<CarView, CarIndex>() 
         .ProjectFromIndexFieldsInto<CarView>() 
         .Where(x => x.PersonId == 1).Lazily(); 
        var person = session.Advanced.Lazily.Load<Person>(1); 

        var personValue = person.Value; 
        var resultsValue = resultsForId1.Value; 
        Assert.Equal("A", personValue.Name); // person data loaded 
        Assert.Equal("A", resultsValue.First().Name); // cars data loaded 
        Assert.Equal(1, server.Server.NumberOfRequests); // only one request sent to the server 
       } 
      } 
     } 
    } 

    public class CarIndex : AbstractIndexCreationTask<Car, CarView> 
    { 
     public CarIndex() 
     { 
      Map = cars => from car in cars 
          select new 
          { 
           car.Id, 
           car.Name, 
           car.PersonId, 
          }; 
     } 
    } 

    public class Person 
    { 
     public int Id { get; set; } 
     public string Name { get; set; } 
     public string Surname { get; set; } 
     public DateTime? BirthDate { get; set; } 
    } 

    public class Car 
    { 
     public int Id { get; set; } 
     public string Name { get; set; } 
     public int PersonId { get; set; } 
    } 

    public class CarView 
    { 
     public int Id { get; set; } 
     public string Name { get; set; } 
     public int PersonId { get; set; } 
    } 
} 
2

你可以這樣說:

using (IDocumentSession session = store.OpenSession()) 
{ 
    var carsForOne = session.Query<Car>() 
      .Include(x=>x.PersonId) 
      .Where(x=>x.PersonId == "people/1") 
      .ToList(); 

    var person = session.Load<Person>("people/1"); 
} 

本作只是一個單一的數據庫請求。