Created
March 29, 2011 16:13
-
-
Save felipeleusin/892649 to your computer and use it in GitHub Desktop.
Implements IEntityDuplicateChecker to use with RavenDB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class EntitySignatureIndexGenerator | |
{ | |
private readonly IDocumentStore documentStore; | |
public EntitySignatureIndexGenerator(IDocumentStore documentStore) | |
{ | |
this.documentStore = documentStore; | |
} | |
public bool CreateIndexForAssembly(Assembly targetAssembly) | |
{ | |
var entityTypes = from type in targetAssembly.GetTypes() where type.BaseType == typeof(RavenEntity) select type; | |
foreach (var entityType in entityTypes) | |
{ | |
var tag = this.documentStore.Conventions.GetTypeTagName(entityType); | |
var indexDefinition = BuildIndexDefinition(entityType, tag); | |
this.documentStore.DatabaseCommands.PutIndex(tag + "/DomainSignature", indexDefinition); | |
} | |
return true; | |
} | |
private static IndexDefinition BuildIndexDefinition(Type entityType, string entityTagName) | |
{ | |
var def = new IndexDefinition(); | |
var mapBuilder = new StringBuilder(); | |
mapBuilder.Append(@"Id = doc[""@metadata""][""@id""],"); | |
def.Indexes.Add("Id", FieldIndexing.NotAnalyzed); | |
def.Stores.Add("Id", FieldStorage.No); | |
foreach (var signatureProperty in entityType.GetProperties().Where(p => Attribute.IsDefined(p, typeof(DomainSignatureAttribute), true))) | |
{ | |
mapBuilder.AppendFormat("doc.{0},", signatureProperty.Name); | |
def.Indexes.Add(signatureProperty.Name, FieldIndexing.NotAnalyzed); | |
def.Stores.Add(signatureProperty.Name, FieldStorage.No); | |
} | |
mapBuilder.Length--; | |
def.Map = String.Format("from doc in docs.{0} select new {{ {1} }}", entityTagName, mapBuilder); | |
return def; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class RavenEntityDuplicateIdChecker : IEntityDuplicateChecker | |
{ | |
private readonly IDocumentSession session; | |
public RavenEntityDuplicateIdChecker(IDocumentSession session) | |
{ | |
this.session = session; | |
} | |
public bool DoesDuplicateExistWithTypedIdOf<IdT>(IEntityWithTypedId<IdT> entity) | |
{ | |
var indexName = this.session.Advanced.Conventions.GetTypeTagName(entity.GetType()) + "/DomainSignature"; | |
var queryBuilder = new StringBuilder(); | |
AppendSignaturePropertyQueryTo(queryBuilder, entity); | |
var query = new IndexQuery { Query = queryBuilder.ToString(), PageSize = 1 }; | |
var queryResult = this.session.Advanced.DatabaseCommands.Query(indexName, query, null); | |
if (queryResult.Results.Count > 0) | |
{ | |
var returnedId = queryResult.Results[0].SelectToken("@metadata").Value<string>("@id"); | |
if (!returnedId.Equals(entity.Id.ToString(), StringComparison.InvariantCultureIgnoreCase)) | |
{ | |
return true; | |
} | |
} | |
return false; | |
} | |
private static void AppendSignaturePropertyQueryTo<IdT>(StringBuilder query, IEntityWithTypedId<IdT> entity) | |
{ | |
foreach (var signatureProperty in entity.GetSignatureProperties()) | |
{ | |
var name = signatureProperty.Name; | |
var propertyType = signatureProperty.PropertyType; | |
var propertyValue = signatureProperty.GetValue(entity, null); | |
if (propertyType.IsEnum) | |
{ | |
query.Append(name + ":" + (int)propertyValue + " "); | |
} | |
else if (propertyType.GetInterfaces().Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IEntityWithTypedId<>))) | |
{ | |
AppendEntityQueryTo<IdT>(query, signatureProperty, propertyValue); | |
} | |
else if (propertyType == typeof(DateTime)) | |
{ | |
AppendDateTimePropertyQueryTo(query, signatureProperty, propertyValue); | |
} | |
else if (propertyType == typeof(string)) | |
{ | |
AppendStringPropertyQueryTo(query, signatureProperty, propertyValue); | |
} | |
else if (propertyType.IsValueType) | |
{ | |
AppendValuePropertyQueryTo(query, signatureProperty, propertyValue); | |
} | |
else | |
{ | |
throw new ApplicationException("Can't determine how to use " + entity.GetType() + "." + | |
signatureProperty.Name + " when looking for duplicate entries. To remedy this, " + | |
"you can create a custom validator or report an issue to the S#arp Architecture " + | |
"project, detailing the type that you'd like to be accommodated."); | |
} | |
} | |
} | |
private static void AppendStringPropertyQueryTo(StringBuilder query, PropertyInfo signatureProperty, object propertyValue) | |
{ | |
query.AppendFormat("{0}:{1} ", signatureProperty.Name, propertyValue != null ? "\"" + propertyValue + "\"" : "[[NULL_VALUE]]"); | |
} | |
private static void AppendDateTimePropertyQueryTo(StringBuilder query, PropertyInfo signatureProperty, object propertyValue) | |
{ | |
query.AppendFormat("{0}:{1} ", signatureProperty.Name, (DateTime)propertyValue > default(DateTime) ? ((DateTime)propertyValue).ToString("yyyyMMdd") : "[[NULL_VALUE]]"); | |
} | |
private static void AppendValuePropertyQueryTo(StringBuilder query, PropertyInfo signatureProperty, object propertyValue) | |
{ | |
query.AppendFormat("{0}:{1} ", signatureProperty.Name, propertyValue ?? "[[NULL_VALUE]]"); | |
} | |
private static void AppendEntityQueryTo<IdT>(StringBuilder query, PropertyInfo signatureProperty, object propertyValue) | |
{ | |
if (propertyValue != null) | |
{ | |
query.AppendFormat("{0}:{1} ", signatureProperty.Name + ".Id", ((IEntityWithTypedId<IdT>)propertyValue).Id); | |
} | |
else | |
{ | |
query.AppendFormat("{0}:{1} ", signatureProperty.Name, "[[NULL_VALUE]]"); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment