2017-01-09 28 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"); 
} 

本作只是一个单一的数据库请求。