//■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ private static void ConfigureAddedEntries(DbContext context, IGrouping <EntityState, EntityEntry> state, object[] languageKey) { int parameterPosition; foreach (var entry in state) { var translationEntity = TranslationConfiguration.TranslationEntities[entry.Entity.GetType().FullName]; PersistenceHelpers.ValidateLanguageKeys(translationEntity.KeysFromLanguageEntity, languageKey); var translation = Activator.CreateInstance(translationEntity.Type); foreach (var property in entry.Entity.GetType().GetProperties()) { translationEntity.Type.GetProperty(property.Name)?.SetValue(translation, property.GetValue(entry.Entity)); } parameterPosition = 0; foreach (var property in translationEntity.KeysFromLanguageEntity) { context.Entry(translation).Property(property.Name).CurrentValue = languageKey[parameterPosition]; parameterPosition++; } foreach (var property in translationEntity.KeysFromSourceEntity) { context.Entry(translation).Property(property.Value).CurrentValue = entry.Entity.GetType().GetProperty(property.Key).GetValue(entry.Entity); } context.Entry(translation).State = EntityState.Added; } }
internal static IQueryable <TEntity> GetTranslatedQuery <TEntity>(this IQueryable <TEntity> query, object[] desiredLanguageKey, object[] defaultLanguageKey, Expression <Func <TEntity, bool> > predicate = null) where TEntity : class { var context = PersistenceHelpers.GetDbContext(query); var translationEntity = TranslationConfiguration.TranslationEntities[typeof(TEntity).FullName]; PersistenceHelpers.ValidateLanguageKeys(translationEntity.KeysFromLanguageEntity, desiredLanguageKey, defaultLanguageKey); var baseQuery = context.GetType() .GetMethod("Query") .MakeGenericMethod(translationEntity.Type); var defaultTranslationQuery = (IQueryable <object>)baseQuery.Invoke(context, null); var desiredTranslationQuery = (IQueryable <object>)baseQuery.Invoke(context, null); int parameterPosition = 0; foreach (var property in translationEntity.KeysFromLanguageEntity) { defaultTranslationQuery = defaultTranslationQuery.Where(BuildPredicate(property.Name, defaultLanguageKey[parameterPosition])); desiredTranslationQuery = desiredTranslationQuery.Where(BuildPredicate(property.Name, desiredLanguageKey[parameterPosition])); parameterPosition++; } var sourceKeys = translationEntity.KeysFromSourceEntity.Select(key => key.Key); var relationshipKeys = translationEntity.KeysFromSourceEntity.Select(key => key.Value); if (predicate != null) { query = query.Where(predicate); } var wanted = query //Fallback .Join( defaultTranslationQuery, GetKeys <TEntity>(sourceKeys), GetKeys <object>(relationshipKeys), (Entity, Translation) => new QueryJoinHelper <TEntity> { Entity = Entity, Translation = Translation }) //Wanted .GroupJoin( desiredTranslationQuery, GetKeysFromGroup <QueryJoinHelper <TEntity>, TEntity>(sourceKeys), GetKeys <object>(relationshipKeys), (Base, Translation) => new { Base, Translation }) .SelectMany(result => result.Translation.DefaultIfEmpty(), (From, Translation) => From.Base.Entity.SetTranslatedProperties(Translation ?? From.Base.Translation)); return(wanted); }
//■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ private static void ConfigureModifiedEntries(DbContext context, IGrouping <EntityState, EntityEntry> state, object[] languageKey) { int parameterPosition; foreach (var entry in state) { var translationEntity = TranslationConfiguration.TranslationEntities[entry.Entity.GetType().FullName]; PersistenceHelpers.ValidateLanguageKeys(translationEntity.KeysFromLanguageEntity, languageKey); var translatedEntry = context.ChangeTracker.Entries().Where(e => { if (e.Entity.GetType() != translationEntity.Type) { return(false); } parameterPosition = 0; foreach (var property in translationEntity.KeysFromLanguageEntity) { if (!e.Property(property.Name).CurrentValue.Equals(languageKey[parameterPosition])) { return(false); } } foreach (var property in translationEntity.KeysFromSourceEntity) { if (!e.Property(property.Value).CurrentValue.Equals(entry.Property(property.Key).CurrentValue)) { return(false); } } return(true); }).SingleOrDefault(); if (translatedEntry == null) { throw new ArgumentNullException($"Could not find the translated entry for the {entry.Entity.GetType().Name} entry"); } foreach (var property in entry.Entity.GetType().GetProperties()) { if (translationEntity.Type.GetProperty(property.Name) != null) { context.Entry(translatedEntry.Entity).Property(property.Name).CurrentValue = property.GetValue(entry.Entity); } } } }
//═════════════════════════════════════════════════════════════════════════════════════════ public static void UpsertTranslationRange <TEntity>([NotNull] this IQueryable <TEntity> source, TEntity entity, params Translation <TEntity>[] translationEntities) where TEntity : class { int parameterPosition; var context = PersistenceHelpers.GetDbContext(source); var translationEntity = TranslationConfiguration.TranslationEntities[typeof(TEntity).FullName]; var method = getExistingTranslationsMethod.MakeGenericMethod(typeof(TEntity), translationEntity.Type); IEnumerable <IDictionary <string, object> > existingTranslations = null; PersistenceHelpers.ValidateLanguageKeys(translationEntity.KeysFromLanguageEntity, translationEntities.SelectMany(translation => translation.LanguageKey).ToArray()); foreach (var entry in translationEntities) { var translation = Activator.CreateInstance(translationEntity.Type); var trackedEntity = context.ChangeTracker.Entries().Where(entry => entry.Entity.GetType() == translationEntity.Type); foreach (var property in entry.Entity.GetType().GetProperties()) { translationEntity.Type.GetProperty(property.Name)?.SetValue(translation, property.GetValue(entry.Entity)); } parameterPosition = 0; foreach (var property in translationEntity.KeysFromLanguageEntity) { context.Entry(translation).Property(property.Name).CurrentValue = entry.LanguageKey[parameterPosition]; trackedEntity = trackedEntity.Where(entry => entry.Property(property.Name).CurrentValue.Equals(context.Entry(translation).Property(property.Name).CurrentValue)); parameterPosition++; } foreach (var property in translationEntity.KeysFromSourceEntity) { context.Entry(translation).Property(property.Value).CurrentValue = entity.GetType().GetProperty(property.Key).GetValue(entity); trackedEntity = trackedEntity.Where(entry => entry.Property(property.Value).CurrentValue.Equals(context.Entry(translation).Property(property.Value).CurrentValue)); } var tracked = trackedEntity.SingleOrDefault(); if (tracked != null) { foreach (var property in tracked.Entity.GetType().GetProperties() .Where(property => !translationEntity.KeysFromLanguageEntity.Select(key => key.Name).Contains(property.Name) || !translationEntity.KeysFromSourceEntity.Select(key => key.Value).Contains(property.Name))) { tracked.Property(property.Name).CurrentValue = context.Entry(translation).Property(property.Name).CurrentValue; } } else { existingTranslations ??= ((IEnumerable <IDictionary <string, object> >)method.Invoke(null, new object[] { context, entity, translationEntity, translationEntities })).ToList(); var existingTranslation = existingTranslations.AsQueryable(); foreach (var property in context.Entry(translation).Properties .Where(property => translationEntity.KeysFromLanguageEntity.Select(key => key.Name).Contains(property.Metadata.Name) || translationEntity.KeysFromSourceEntity.Select(key => key.Value).Contains(property.Metadata.Name))) { existingTranslation = existingTranslation.Where(translation => translation[property.Metadata.Name].Equals(property.CurrentValue)); } if (existingTranslation.Count() > 0) { context.Entry(translation).State = EntityState.Modified; } else { context.Entry(translation).State = EntityState.Added; } } } }