/// <summary> /// Try get by classifier /// </summary> public static IIdentifiedEntity TryGetExisting(this IIdentifiedEntity me, ModelDataContext context, IPrincipal principal) { // Is there a classifier? var idpType = typeof(IDataPersistenceService <>).MakeGenericType(me.GetType()); var idpInstance = ApplicationContext.Current.GetService(idpType); IIdentifiedEntity existing = null; // Is the key not null? if (me.Key != Guid.Empty && me.Key != null) { // We have to find it var getMethod = idpInstance.GetType().GetRuntimeMethods().SingleOrDefault(o => o.Name == "Get" && o.GetParameters().Length == 3 && o.GetParameters()[0].ParameterType == typeof(ModelDataContext)); if (getMethod == null) { return(null); } existing = getMethod.Invoke(idpInstance, new object[] { context, me.Key, principal }) as IIdentifiedEntity; } var classAtt = me.GetType().GetCustomAttribute <KeyLookupAttribute>(); if (classAtt != null) { object classifierValue = me; // me.GetType().GetProperty(classAtt.ClassifierProperty).GetValue(me); // Follow the classifier Type predicateType = typeof(Func <,>).MakeGenericType(me.GetType(), typeof(bool)); ParameterExpression parameterExpr = Expression.Parameter(me.GetType(), "o"); Expression accessExpr = parameterExpr; while (classAtt != null) { var property = accessExpr.Type.GetRuntimeProperty(classAtt.UniqueProperty); accessExpr = Expression.MakeMemberAccess(accessExpr, property); classifierValue = property.GetValue(classifierValue); classAtt = accessExpr.Type.GetCustomAttribute <KeyLookupAttribute>(); } // public abstract IQueryable<TData> Query(ModelDataContext context, Expression<Func<TData, bool>> query, IPrincipal principal); var queryMethod = idpInstance.GetType().GetRuntimeMethods().SingleOrDefault(o => o.Name == "Query" && o.GetParameters().Length == 3 && o.GetParameters()[0].ParameterType == typeof(ModelDataContext)); var builderMethod = typeof(Expression).GetGenericMethod(nameof(Expression.Lambda), new Type[] { predicateType }, new Type[] { typeof(Expression), typeof(ParameterExpression[]) }); var expression = builderMethod.Invoke(null, new object[] { Expression.MakeBinary(ExpressionType.Equal, accessExpr, Expression.Convert(Expression.Constant(classifierValue), accessExpr.Type)), new ParameterExpression[] { parameterExpr } }) as Expression; if (queryMethod == null) { return(null); } var iq = queryMethod.Invoke(idpInstance, new object[] { context, expression, principal }) as IQueryable; foreach (var i in iq) { existing = i as IIdentifiedEntity; me.Key = existing.Key; if (me is IVersionedEntity) { (me as IVersionedEntity).VersionKey = (existing as IVersionedEntity)?.VersionKey ?? Guid.Empty; } } } return(existing); }
/// <summary> /// Ensures a model has been persisted /// </summary> public static void EnsureExists(this IIdentifiedEntity me, ModelDataContext context, IPrincipal principal) { // Me var vMe = me as IVersionedEntity; String dkey = String.Format("{0}.{1}", me.GetType().FullName, me.Key); IIdentifiedEntity existing = me.TryGetExisting(context, principal); var idpType = typeof(IDataPersistenceService <>).MakeGenericType(me.GetType()); var idpInstance = ApplicationContext.Current.GetService(idpType); // Existing exists? if (existing != null && me.Key.HasValue) { // Exists but is an old version if ((existing as IVersionedEntity)?.VersionKey != vMe?.VersionKey && vMe?.VersionKey != null && vMe?.VersionKey != Guid.Empty) { // Update method var updateMethod = idpInstance.GetType().GetRuntimeMethods().SingleOrDefault(o => o.Name == "Update" && o.GetParameters().Length == 3 && o.GetParameters()[0].ParameterType == typeof(ModelDataContext)); if (updateMethod != null) { IVersionedEntity updated = updateMethod.Invoke(idpInstance, new object[] { context, me, principal }) as IVersionedEntity; me.Key = updated.Key; if (vMe != null) { vMe.VersionKey = (updated as IVersionedEntity).VersionKey; } } } } else // Insert { var insertMethod = idpInstance.GetType().GetRuntimeMethods().SingleOrDefault(o => o.Name == "Insert" && o.GetParameters().Length == 3 && o.GetParameters()[0].ParameterType == typeof(ModelDataContext)); if (insertMethod != null) { IIdentifiedEntity inserted = insertMethod.Invoke(idpInstance, new object[] { context, me, principal }) as IIdentifiedEntity; me.Key = inserted.Key; if (vMe != null) { vMe.VersionKey = (inserted as IVersionedEntity).VersionKey; } } } }
/// <summary> /// Ensures a model has been persisted /// </summary> public static IIdentifiedEntity EnsureExists(this IIdentifiedEntity me, DataContext context, IPrincipal principal) { if (me == null) { return(null); } // Me var vMe = me as IVersionedEntity; String dkey = String.Format("{0}.{1}", me.GetType().FullName, me.Key); IIdentifiedEntity existing = me.TryGetExisting(context, principal); var idpInstance = AdoAuditPersistenceService.GetPersister(me.GetType()); // Existing exists? if (existing != null && me.Key.HasValue) { // Exists but is an old version if ((existing as IVersionedEntity)?.VersionKey != vMe?.VersionKey && vMe?.VersionKey != null && vMe?.VersionKey != Guid.Empty) { // Update method IVersionedEntity updated = idpInstance.Update(context, me) as IVersionedEntity; me.Key = updated.Key; if (vMe != null) { vMe.VersionKey = (updated as IVersionedEntity).VersionKey; } return(updated); } return(existing); } else if (existing == null) // Insert { IIdentifiedEntity inserted = idpInstance.Insert(context, me) as IIdentifiedEntity; me.Key = inserted.Key; if (vMe != null) { vMe.VersionKey = (inserted as IVersionedEntity).VersionKey; } return(inserted); } return(existing); }
/// <summary> /// Try get by classifier /// </summary> public static bool CheckExists(this IIdentifiedEntity me, DataContext context) { // Is there a classifier? var serviceInstance = ApplicationServiceContext.Current.GetService <AdoPersistenceService>(); var idpInstance = serviceInstance.GetPersister(me.GetType()) as IAdoPersistenceService; if (me.Key.HasValue && me.Key != Guid.Empty) { return(idpInstance.Exists(context, me.Key.GetValueOrDefault())); } else { return(false); } }
/// <summary> /// Updates a keyed delay load field if needed /// </summary> public static void UpdateParentKeys(this IIdentifiedEntity instance, PropertyInfo field) { var delayLoadProperty = field.GetCustomAttribute <SerializationReferenceAttribute>(); if (delayLoadProperty == null || String.IsNullOrEmpty(delayLoadProperty.RedirectProperty)) { return; } var value = field.GetValue(instance) as IIdentifiedEntity; if (value == null) { return; } // Get the delay load key property! var keyField = instance.GetType().GetRuntimeProperty(delayLoadProperty.RedirectProperty); keyField.SetValue(instance, value.Key); }
/// <summary> /// Try get by classifier /// </summary> public static IIdentifiedEntity TryGetExisting(this IIdentifiedEntity me, LocalDataContext context, bool forceDbSearch = false) { // Is there a classifier? var idpInstance = LocalPersistenceService.GetPersister(me.GetType()) as ILocalPersistenceService; if (idpInstance == null) { return(null); } //if (me.Key?.ToString() == "e4d3350b-b0f5-45c1-80ba-49e3844cbcc8") // System.Diagnostics.Debugger.Break(); IIdentifiedEntity existing = null; if (me.Key != null) { existing = context.TryGetCacheItem(me.Key.Value); } if (existing != null) { return(existing); } else if (!context.Connection.IsInTransaction) { existing = context.TryGetData(me.Key.Value.ToString()) as IdentifiedData; } else if (me.Key.HasValue) { existing = context.FindTransactedItem(me.Key.Value); } if (forceDbSearch && me.Key.HasValue) { ApplicationContext.Current.GetService <IDataCachingService>().Remove(me.Key.Value); } // Is the key not null? if (me.Key != Guid.Empty && me.Key != null && existing == null) { existing = idpInstance.Get(context, me.Key.Value) as IIdentifiedEntity; } var classAtt = me.GetType().GetTypeInfo().GetCustomAttribute <KeyLookupAttribute>(); if (classAtt != null && existing == null) { // Get the domain type var dataType = LocalPersistenceService.Mapper.MapModelType(me.GetType()); var tableMap = TableMapping.Get(dataType); // Get the classifier attribute value var classProperty = me.GetType().GetRuntimeProperty(classAtt.UniqueProperty); object classifierValue = classProperty.GetValue(me); // Get the classifier // Is the classifier a UUID'd item? if (classifierValue is IIdentifiedEntity) { classifierValue = (classifierValue as IIdentifiedEntity).Key.Value; classProperty = me.GetType().GetRuntimeProperty(classProperty.GetCustomAttribute <SerializationReferenceAttribute>()?.RedirectProperty ?? classProperty.Name); } // Column var column = tableMap.GetColumn(LocalPersistenceService.Mapper.MapModelProperty(me.GetType(), dataType, classProperty)); // Now we want to query SqlStatement stmt = new SqlStatement().SelectFrom(dataType) .Where($"{column.Name} = ?", classifierValue).Build(); var mapping = context.Connection.GetMapping(dataType); var dataObject = context.Connection.Query(mapping, stmt.SQL, stmt.Arguments.ToArray()).FirstOrDefault(); if (dataObject != null) { existing = idpInstance.ToModelInstance(dataObject, context) as IIdentifiedEntity; } } if (existing != null && me.Key.HasValue) { context.AddData(me.Key.Value.ToString(), existing); } return(existing); }
/// <summary> /// Try get by classifier /// </summary> public static IIdentifiedEntity TryGetExisting(this IIdentifiedEntity me, DataContext context, IPrincipal principal, bool forceDatabase = false) { // Is there a classifier? var idpInstance = AdoAuditPersistenceService.GetPersister(me.GetType()) as IAdoPersistenceService; var cacheService = ApplicationServiceContext.Current.GetService <IDataCachingService>(); IIdentifiedEntity existing = null; // Forcing from database load from if (forceDatabase && me.Key.HasValue) { // HACK: This should really hit the database instead of just clearing the cache ApplicationServiceContext.Current.GetService <IDataCachingService>()?.Remove(me.Key.Value); } //var tableType = AdoPersistenceService.GetMapper().MapModelType(me.GetType()); //if (me.GetType() != tableType) //{ // var tableMap = TableMapping.Get(tableType); // var dbExisting = context.FirstOrDefault(tableType, context.CreateSqlStatement().SelectFrom(tableType).Where($"{tableMap.Columns.FirstOrDefault(o=>o.IsPrimaryKey).Name}=?", me.Key.Value)); // if (dbExisting != null) // existing = idpInstance.ToModelInstance(dbExisting, context, principal) as IIdentifiedEntity; //} if (me.Key != Guid.Empty && me.Key != null) { existing = idpInstance.Get(context, me.Key.Value) as IIdentifiedEntity; } var classAtt = me.GetType().GetCustomAttribute <KeyLookupAttribute>(); if (classAtt != null && existing == null) { // Get the domain type var dataType = AdoAuditPersistenceService.GetMapper().MapModelType(me.GetType()); var tableMap = TableMapping.Get(dataType); // Get the classifier attribute value var classProperty = me.GetType().GetProperty(classAtt.UniqueProperty); object classifierValue = classProperty.GetValue(me); // Get the classifier // Is the classifier a UUID'd item? if (classifierValue is IIdentifiedEntity) { classifierValue = (classifierValue as IIdentifiedEntity).Key.Value; classProperty = me.GetType().GetProperty(classProperty.GetCustomAttribute <SerializationReferenceAttribute>()?.RedirectProperty ?? classProperty.Name); } // Column var column = tableMap.GetColumn(AdoAuditPersistenceService.GetMapper().MapModelProperty(me.GetType(), dataType, classProperty)); // Now we want to query SqlStatement stmt = context.CreateSqlStatement().SelectFrom(dataType) .Where($"{column.Name} = ?", classifierValue); Guid objIdCache = Guid.Empty; IDbIdentified dataObject = null; // We've seen this before String classKey = $"{dataType}.{classifierValue}"; if (m_classIdCache.TryGetValue(classKey, out objIdCache)) { existing = cacheService?.GetCacheItem(objIdCache) as IdentifiedData ?? context.GetCacheCommit(objIdCache); } if (existing == null) { dataObject = context.FirstOrDefault(dataType, stmt) as IDbIdentified; if (dataObject != null) { lock (m_classIdCache) if (!m_classIdCache.ContainsKey(classKey)) { m_classIdCache.Add(classKey, dataObject.Key); } var existCache = cacheService?.GetCacheItem((dataObject as IDbIdentified).Key); if (existCache != null) { existing = existCache as IdentifiedData; } else { existing = idpInstance.ToModelInstance(dataObject, context) as IIdentifiedEntity; } } } } return(existing); }
/// <summary> /// Ensures a model has been persisted /// </summary> public static IIdentifiedEntity EnsureExists(this IIdentifiedEntity me, DataContext context, bool createIfNotExists = true, Type ensureType = null) { if (me == null) { return(null); } // Me var serviceInstance = ApplicationServiceContext.Current.GetService <AdoPersistenceService>(); var vMe = me as IVersionedEntity; var idpInstance = serviceInstance.GetPersister(ensureType ?? me.GetType()); IIdentifiedEntity existing = me.TryGetExisting(context) ?? idpInstance.Get(context, me.Key.GetValueOrDefault()) as IIdentifiedEntity; // Don't touch the child just return reference if (!serviceInstance.GetConfiguration().AutoInsertChildren || !createIfNotExists) { if (existing != null) { if (me.Key != existing.Key || vMe?.VersionKey != (existing as IVersionedEntity)?.VersionKey) { me.CopyObjectData(existing); // copy data into reference } return(existing); } else { throw new KeyNotFoundException(me.Key.Value.ToString()); } } // Existing exists? if (existing != null && me.Key.HasValue) { // Exists but is an old version if ((existing as IVersionedEntity)?.VersionSequence < vMe?.VersionSequence && vMe?.VersionKey != null && vMe?.VersionKey != Guid.Empty) { // Update method IVersionedEntity updated = idpInstance.Update(context, me) as IVersionedEntity; me.Key = updated.Key; if (vMe != null) { vMe.VersionKey = (updated as IVersionedEntity).VersionKey; } return(updated); } return(existing); } else if (existing == null) // Insert { IIdentifiedEntity inserted = idpInstance.Insert(context, me) as IIdentifiedEntity; me.Key = inserted.Key; if (vMe != null) { vMe.VersionKey = (inserted as IVersionedEntity).VersionKey; } return(inserted); } return(existing); }
/// <summary> /// Delay load property /// </summary> public static object LoadProperty(this IIdentifiedEntity me, string propertyName, bool forceReload = false) { if (me == null) { return(null); } var propertyToLoad = me.GetType().GetRuntimeProperty(propertyName); if (propertyToLoad == null) { return(null); } var currentValue = propertyToLoad.GetValue(me); var loadCheck = new PropertyLoadCheck(propertyName); if (!forceReload && (me.GetAnnotations <PropertyLoadCheck>().Contains(loadCheck) || me.GetAnnotations <String>().Contains(SanteDBConstants.NoDynamicLoadAnnotation))) { return(currentValue); } else if (forceReload) { currentValue = null; } try { if (typeof(IList).IsAssignableFrom(propertyToLoad.PropertyType)) // Collection we load by key { if ((currentValue == null || (currentValue as IList)?.Count == 0) && me.Key.HasValue) { var mi = typeof(IEntitySourceProvider).GetGenericMethod(nameof(IEntitySourceProvider.GetRelations), new Type[] { propertyToLoad.PropertyType.StripGeneric() }, new Type[] { typeof(Guid?[]) }); object loaded = null; if (me is ITaggable taggable && taggable.TryGetTag(SanteDBConstants.AlternateKeysTag, out ITag altKeys)) { loaded = Activator.CreateInstance(propertyToLoad.PropertyType, mi.Invoke(EntitySource.Current.Provider, new Object[] { altKeys.Value.Split(',').Select(o => (Guid?)Guid.Parse(o)).Union(new Guid?[] { me.Key }).ToArray() })); } else { loaded = Activator.CreateInstance(propertyToLoad.PropertyType, mi.Invoke(EntitySource.Current.Provider, new object[] { new Guid?[] { me.Key.Value } })); } propertyToLoad.SetValue(me, loaded); return(loaded); } return(currentValue); } else if (currentValue == null) { var keyValue = propertyToLoad.GetSerializationRedirectProperty()?.GetValue(me) as Guid?; if (keyValue.GetValueOrDefault() == default(Guid)) { return(currentValue); } else { var mi = typeof(IEntitySourceProvider).GetGenericMethod(nameof(IEntitySourceProvider.Get), new Type[] { propertyToLoad.PropertyType }, new Type[] { typeof(Guid?) }); var loaded = mi.Invoke(EntitySource.Current.Provider, new object[] { keyValue }); propertyToLoad.SetValue(me, loaded); return(loaded); } } else { return(currentValue); } }
/// <summary> /// Ensures a model has been persisted /// </summary> public static IIdentifiedEntity EnsureExists(this IIdentifiedEntity me, DataContext context, IPrincipal principal) { if (me == null) { return(null); } // Me var vMe = me as IVersionedEntity; String dkey = String.Format("{0}.{1}", me.GetType().FullName, me.Key); IIdentifiedEntity existing = me.TryGetExisting(context, principal); var idpInstance = AdoPersistenceService.GetPersister(me.GetType()); // Don't touch the child just return reference if (!AdoPersistenceService.GetConfiguration().AutoInsertChildren) { if (existing != null) { if (me.Key != existing.Key || vMe?.VersionKey != (existing as IVersionedEntity)?.VersionKey) { me.CopyObjectData(existing); // copy data into reference } return(existing); } else { throw new KeyNotFoundException(me.Key.Value.ToString()); } } // Existing exists? if (existing != null && me.Key.HasValue) { // Exists but is an old version if ((existing as IVersionedEntity)?.VersionKey != vMe?.VersionKey && vMe?.VersionKey != null && vMe?.VersionKey != Guid.Empty) { // Update method IVersionedEntity updated = idpInstance.Update(context, me, principal) as IVersionedEntity; me.Key = updated.Key; if (vMe != null) { vMe.VersionKey = (updated as IVersionedEntity).VersionKey; } return(updated); } return(existing); } else if (existing == null) // Insert { IIdentifiedEntity inserted = idpInstance.Insert(context, me, principal) as IIdentifiedEntity; me.Key = inserted.Key; if (vMe != null) { vMe.VersionKey = (inserted as IVersionedEntity).VersionKey; } return(inserted); } return(existing); }
public static string GetTypeId(this IIdentifiedEntity entity) { return(entity.GetType().FullName); }