Non sono sicuro se questo va abbastanza lontano per rispondere alla tua domanda, ma ecco come posso fare per creare un riferimento denormalizzato in RavenDB (questo è preso dal codice vero e proprio con i non-essenziali rimosse per chiarezza)
Domain
public class User : IUserIdentity
{
public string UserName { get; set; }
public IEnumerable<string> Claims { get; set; }
public string Id { get; set; }
public Guid FormsAuthenticationGuid { get; set; }
}
public class Assessment
{
public string Id { get; set; }
public UserReference User { get; set; }
public AssessmentState State { get; set; }
}
Si può vedere che ho una classe Assessment
che fa riferimento a un User
. Questo riferimento utente è gestito utilizzando la classe UserReference
di seguito.
denormalizzato Riferimento
public class UserReference
{
public string Id { get; set; }
public string UserName { get; set; }
public static implicit operator UserReference(User user)
{
return new UserReference
{
Id = user.Id,
UserName = user.UserName
};
}
}
nota come la classe di riferimento porta anche il UserName
. Questo valore non cambierà molto spesso ma potrebbe cambiare, pertanto è necessario un modo per aggiornare la proprietà UserName
nella proprietà UserReference
detenuta nella classe Assessment
. Per effettuare la modifica dobbiamo prima trovare le istanze corrette Assessment
da RavenDB e per questo abbiamo bisogno di un indice.
Raven Indice
public class Assessment_ByUserId : AbstractIndexCreationTask<Assessment>
{
public Assessment_ByUserId()
{
Map = assessments => from assessment in assessments
select new
{
User_Id = assessment.User.Id
};
}
}
Questo indice deve essere invocato ogni volta che UserName
valore s' un User
viene aggiornato. Ho una classe UserService
che mi aiuta a coordinare tutte le mie funzioni relative all'utente, quindi è qui che inserisco questo codice.
Riutilizzo questo codice per altri riferimenti, quindi è stato un po 'astratto. Questo può aiutarti a creare le gerarchie più complesse (o forse "il grafico del dominio" è una descrizione migliore) che desideri.
UserService
public static void SetUserName(IDocumentSession db, string userId, string userName)
{
var user = db.Load<User>(userId);
user.UserName = userName;
db.Save(user);
UpdateDenormalizedReferences(db, user, userName);
}
private static void UpdateDenormalizedReferences(IDocumentSession db, User user, string userName)
{
db.Advanced.DatabaseCommands.UpdateByIndex(
RavenIndexes.IndexAssessmentByUserId,
GetQuery(user.Id),
GetUserNamePatch(userName),
allowStale: true);
}
private static IndexQuery GetQuery(string propertyValue, string propertyName = "User_Id")
{
return new IndexQuery {Query = string.Format("{0}:{1}", propertyName, propertyValue)};
}
private static PatchRequest[] GetUserNamePatch(string referenceValue, string referenceName = "User")
{
return new[]
{
new PatchRequest
{
Type = PatchCommandType.Modify,
Name = referenceName,
Nested = new[]
{
new PatchRequest
{
Type = PatchCommandType.Set,
Name = "UserName",
Value = referenceValue
}
}
}
};
}
che è. E sai, ora che metto tutto fuori posso vedere cosa intendi. È è un sacco di lavoro solo per aggiornare un riferimento. Forse il codice di servizio può essere reso più DRY e riutilizzato per diversi tipi di relazione, ma non vedo come uscire dalla scrittura di molti indici, uno per tipo di riferimento.
Questo post può aiutare a decidere: http://daniellang.net/how-to-handle-relations-in-ravendb/ – dasheddot
Grazie dasheddot, è davvero utile, grazie. –
Questo sembra interessante. Multi Maps/Riduci gli indici [qui] (http: // ayende.com/blog/89089/ravendb-multi-maps-reduce-indexes) – biofractal