/// <summary> /// 获取当前对象中<paramref name="propertyName"/>的值。 /// </summary> /// <param name="model">模型实例。</param> /// <param name="propertyName">属性名称。</param> /// <returns>返回当前属性的值。</returns> protected object GetValue(object model, string propertyName) { if (propertyName == "$site") { return((model as IEnumerable).OfType <object>().Count()); } _entityType = _entityType ?? _model.GetEntity(model.GetType()); return(_entityType?.FindProperty(propertyName)?.Get(model)); }
/// <summary> /// <para> /// Gets a property with the given name. /// </para> /// <para> /// This API only finds scalar properties and does not find navigation properties. Use /// <see cref="FindNavigation(IEntityType, string)" /> to find a navigation property. /// </para> /// </summary> /// <param name="entityType"> The entity type. </param> /// <param name="name"> The property name. </param> /// <returns> The property, or <see langword="null" /> if none is found. </returns> public static IProperty GetProperty([NotNull] this IEntityType entityType, [NotNull] string name) { Check.NotEmpty(name, nameof(name)); var property = entityType.FindProperty(name); if (property == null) { if (entityType.FindNavigation(name) != null) { throw new InvalidOperationException( CoreStrings.PropertyIsNavigation( name, entityType.DisplayName(), nameof(EntityEntry.Property), nameof(EntityEntry.Reference), nameof(EntityEntry.Collection))); } throw new InvalidOperationException(CoreStrings.PropertyNotFound(name, entityType.DisplayName())); } return(property); }
public void Map <TResult>(string name, Expression <Func <TEntity, TResult> > expression) { if (!(expression.Body is MemberExpression member)) { throw new InvalidOperationException("Expected member expression"); } var property = GetPropertyInfo(member); var entityProperty = _entityType.FindProperty(property); if (entityProperty == null) { throw new InvalidOperationException($"The property '{typeof(TEntity).Name}.{property.Name}' is not mapped to entity."); } Configuration.Mappings.Add(new QueryProperty { Alias = name ?? property.Name, PropertyInfo = property }); }
/// <summary> /// 添加列。 /// </summary> /// <typeparam name="T">属性类型。</typeparam> /// <param name="column">列表达式。</param> /// <param name="type">字段类型。</param> /// <param name="unicode">是否为Unicode编码。</param> /// <param name="nullable">是否为空。</param> /// <param name="defaultValue">默认值。</param> /// <param name="defaultValueSql">默认值SQL字符串。</param> /// <param name="computedColumnSql">计算列的SQL字符串。</param> /// <param name="action">添加扩展。</param> /// <returns>返回操作实例。</returns> public virtual CreateTableBuilder <TEntity> Column <T>( Expression <Func <TEntity, T> > column, string type = null, bool?nullable = null, bool?unicode = null, object defaultValue = null, string defaultValueSql = null, string computedColumnSql = null, Action <OperationBuilder <AddColumnOperation> > action = null) { Check.NotNull(column, nameof(column)); var property = _entity.FindProperty(column.GetPropertyAccess().Name); var operation = new AddColumnOperation { Table = Operation.Table, Name = property.Name, ClrType = property.ClrType, ColumnType = type, IsUnicode = unicode, Identity = property.Identity, Seed = property.Seed, Step = property.Step, MaxLength = property.MaxLength, Precision = property.Precision, Scale = property.Scale, IsRowVersion = property.IsRowVersion, IsNullable = nullable ?? property.IsNullable, DefaultValue = defaultValue, DefaultValueSql = defaultValueSql, ComputedColumnSql = computedColumnSql }; Operation.Columns.Add(operation); action?.Invoke(new OperationBuilder <AddColumnOperation>(operation)); return(this); }
public void TestMappingComponent() { // GIVEN a configured application Module module = new Module(); // GIVEN a db context module.AddDbContext <TestDbContext>(cfg => { var connection = new SqliteConnection($"DataSource=file:TestMapping?mode=memory&cache=shared"); connection.Open(); cfg.UseSqlite(connection); }); // GIVEN a configuration module.AddDbContextConfiguration <TestDbContext, TestDbContextConfiguration>(); // WHEN the application is built IServiceCollection services = new ServiceCollection(); module.ConfigureServices(services, null, null); IServiceProvider serviceProvider = services.BuildServiceProvider(); // THEN model configuration is applied TestDbContext dbContext = serviceProvider.GetService <TestDbContext>(); // get the random annotation to check that ConfigureModel was executed. IEntityType entityType = dbContext.Model.FindEntityType(typeof(TestDocument)); IProperty property = entityType.FindProperty("Id"); Assert.Contains(property.GetAnnotations(), a => a.Name == "test annotation"); // THEN mapper configuration is applied ITypeOptions typeOptions = dbContext.GetInfrastructure().GetService <Mapper>().GetTypeOptions(typeof(TestDocument)); Assert.True(typeOptions.GetMember("Name").IsKey); }
/// <summary> /// Get IProperty configuration of the column used by EF. /// </summary> /// <param name="context">DbContext</param> /// <param name="rootEntityType">Entity type to find property of. In case of owned entity specify parent entity type.</param> /// <param name="propertyName">Property of entity. In case of owned entity specify propertyName of format of "NavigationProperty_OwnedEntityProperty".</param> /// <returns></returns> public static IProperty GetPropertyMapping(this DbContext context, Type rootEntityType, string propertyName) { string entityName = TypeExtensions.DisplayName(rootEntityType); IEntityType rootEntity = context.Model.FindEntityType(entityName); if (rootEntity == null) { throw new KeyNotFoundException($"Entity {rootEntityType.FullName} is not found in EntityFramework configuration."); } List <string> propertyNamePath = ReflectionUtility.SplitEfPropertyName(propertyName); IProperty property = null; if (propertyNamePath.Count == 1) { property = rootEntity.FindProperty(propertyName); } else if (propertyNamePath.Count == 2) { string rootEntityNavigationProperty = propertyNamePath[0]; string ownedEntityProperty = propertyNamePath[1]; IEntityType ownedEntity = GetOwnedProperty(context, rootEntity, rootEntityNavigationProperty); property = ownedEntity.FindProperty(ownedEntityProperty); } else { throw new NotImplementedException("More than 1 level of Entity framework owned entities is not supported."); } if (property == null) { throw new KeyNotFoundException($"Property {propertyName} is not found in EntityFramework configuration of {rootEntityType.FullName} type."); } return(property); }
public void Map <TResult>(string name, Expression <Func <TEntity, TResult> > expression) { if (!(expression.Body is MemberExpression member)) { throw new InvalidOperationException("Expected member expression"); } var info = GetPropertyInfo(member); var property = _entityType.FindProperty(info); if (property == null) { throw new InvalidOperationException($"The property '{typeof(TEntity).Name}.{info.Name}' is not mapped to entity."); } Configuration.Mappings.Add(new QueryProperty { Name = name ?? info.Name, Type = info.PropertyType, TableName = Configuration.TableName, ColumnName = property.Relational().ColumnName }); }
public List <Tuple <string, object> > GetInnerValues <T>(IQueryable <T> query, Expression <Func <T, T> > updateFactory, IEntityType entity) where T : class #endif { #if EF5 || EF6 // GET mapping var mapping = entity.Info.EntityTypeMapping.MappingFragment; #elif EFCORE #if NETSTANDARD1_3 Assembly assembly; try { assembly = Assembly.Load(new AssemblyName("Microsoft.EntityFrameworkCore.SqlServer")); } catch (Exception ex) { throw new Exception(ExceptionMessage.BatchOperations_AssemblyNotFound); } if (assembly == null) { throw new Exception(ExceptionMessage.BatchOperations_AssemblyNotFound); } var type = assembly.GetType("Microsoft.EntityFrameworkCore.SqlServerMetadataExtensions"); var sqlServerPropertyMethod = type.GetMethod("SqlServer", new[] { typeof(IProperty) }); #else var assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(x => x.FullName.StartsWith("Microsoft.EntityFrameworkCore.SqlServer")); var postgreSqlAssembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(x => x.FullName.StartsWith("Npgsql.EntityFrameworkCore.PostgreSQL", StringComparison.InvariantCulture)); if (assembly == null && postgreSqlAssembly == null) { throw new Exception(ExceptionMessage.BatchOperations_AssemblyNotFound); } MethodInfo sqlServerPropertyMethod = null; if (assembly != null) { var type = assembly.GetType("Microsoft.EntityFrameworkCore.SqlServerMetadataExtensions"); sqlServerPropertyMethod = type.GetMethod("SqlServer", BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(IProperty) }, null); } else if (postgreSqlAssembly != null) { var type = postgreSqlAssembly.GetType("Microsoft.EntityFrameworkCore.NpgsqlMetadataExtensions"); sqlServerPropertyMethod = type.GetMethod("Npgsql", BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(IProperty) }, null); } #endif #endif // GET updateFactory command var values = ResolveUpdateFromQueryDictValues(updateFactory); var destinationValues = new List <Tuple <string, object> >(); foreach (var value in values) { #if EF5 || EF6 // FIND the mapped column var column = mapping.ScalarProperties.Find(x => x.Name == value.Key); if (column == null) { throw new Exception("The destination column could not be found:" + value.Key); } var columnName = column.ColumnName; #elif EFCORE var property = entity.FindProperty(value.Key); var mappingProperty = sqlServerPropertyMethod.Invoke(null, new[] { property }); var columnNameProperty = mappingProperty.GetType().GetProperty("ColumnName", BindingFlags.Public | BindingFlags.Instance); var columnName = (string)columnNameProperty.GetValue(mappingProperty); #endif if (value.Value is Expression) { // Oops! the value is not resolved yet! ParameterExpression parameterExpression = null; ((Expression)value.Value).Visit((ParameterExpression p) => { if (p.Type == typeof(T)) { parameterExpression = p; } return(p); }); // GET the update value by creating a new select command Type[] typeArguments = { typeof(T), ((Expression)value.Value).Type }; var lambdaExpression = Expression.Lambda(((Expression)value.Value), parameterExpression); var selectExpression = Expression.Call( typeof(Queryable), "Select", typeArguments, Expression.Constant(query), lambdaExpression); var result = Expression.Lambda(selectExpression).Compile().DynamicInvoke(); #if EF5 || EF6 // GET the select command text var commandText = ((IQueryable)result).ToString(); // GET the 'value' part var pos = commandText.IndexOf("AS [value]" + Environment.NewLine + "FROM", StringComparison.InvariantCultureIgnoreCase) != -1 ? commandText.IndexOf("AS [value]" + Environment.NewLine + "FROM", StringComparison.InvariantCultureIgnoreCase) - 6 : commandText.IndexOf(Environment.NewLine + " FROM", StringComparison.InvariantCultureIgnoreCase) != -1 ? commandText.IndexOf(Environment.NewLine + " FROM", StringComparison.InvariantCultureIgnoreCase) - 6 : commandText.IndexOf(Environment.NewLine + "FROM", StringComparison.InvariantCultureIgnoreCase) != -1 ? commandText.IndexOf(Environment.NewLine + "FROM", StringComparison.InvariantCultureIgnoreCase) - 6 : commandText.IndexOf("FROM", StringComparison.InvariantCultureIgnoreCase) - 6; var valueSql = commandText.Substring(6, pos); // Add the destination name valueSql = valueSql.Replace("AS [C1]", ""); var listReplace = new List <string>() { "[Extent1]", "[Extent2]", "[Extent3]", "[Extent4]", "[Extent5]", "[Extent6]", "[Extent7]", "[Extent8]", "[Extent9]", "[Filter1]", "[Filter2]", "[Filter3]", "[Filter4]", "[Filter5]", "[Filter6]", }; // Replace the first value found only! foreach (var itemReplace in listReplace) { if (valueSql.Contains(itemReplace)) { valueSql = valueSql.Replace(itemReplace, "B"); break; } } #elif EFCORE RelationalQueryContext queryContext; var command = ((IQueryable)result).CreateCommand(out queryContext); var commandText = command.CommandText; #if NETSTANDARD1_3 // GET the 'value' part var pos = commandText.IndexOf("AS [value]" + Environment.NewLine + "FROM", StringComparison.CurrentCultureIgnoreCase) != -1 ? commandText.IndexOf("AS [value]" + Environment.NewLine + "FROM", StringComparison.CurrentCultureIgnoreCase) - 6 : commandText.IndexOf(Environment.NewLine + " FROM", StringComparison.CurrentCultureIgnoreCase) != -1 ? commandText.IndexOf(Environment.NewLine + " FROM", StringComparison.CurrentCultureIgnoreCase) - 6 : commandText.IndexOf(Environment.NewLine + "FROM", StringComparison.CurrentCultureIgnoreCase) != -1 ? commandText.IndexOf(Environment.NewLine + "FROM", StringComparison.CurrentCultureIgnoreCase) - 6 : commandText.IndexOf("FROM", StringComparison.CurrentCultureIgnoreCase) - 6; var valueSql = commandText.Substring(6, pos); #else // GET the 'value' part var pos = commandText.IndexOf("AS [value]" + Environment.NewLine + "FROM", StringComparison.InvariantCultureIgnoreCase) != -1 ? commandText.IndexOf("AS [value]" + Environment.NewLine + "FROM", StringComparison.InvariantCultureIgnoreCase) - 6 : commandText.IndexOf(Environment.NewLine + " FROM", StringComparison.InvariantCultureIgnoreCase) != -1 ? commandText.IndexOf(Environment.NewLine + " FROM", StringComparison.InvariantCultureIgnoreCase) - 6 : commandText.IndexOf(Environment.NewLine + "FROM", StringComparison.InvariantCultureIgnoreCase) != -1 ? commandText.IndexOf(Environment.NewLine + "FROM", StringComparison.InvariantCultureIgnoreCase) - 6 : commandText.IndexOf("FROM", StringComparison.InvariantCultureIgnoreCase) - 6; var valueSql = commandText.Substring(6, pos); #endif valueSql = valueSql.Trim(); // Add the destination name valueSql = valueSql.Replace("[x]", "B"); valueSql = valueSql.Replace("[c]", "B"); if (valueSql.Length > 0 && valueSql[0] == '[' && valueSql.IndexOf("]", StringComparison.CurrentCultureIgnoreCase) != -1 && valueSql.IndexOf("]", StringComparison.CurrentCultureIgnoreCase) == valueSql.IndexOf("].[", StringComparison.CurrentCultureIgnoreCase) ) { // Could contains [something].[column] // GET the tag var tagToReplace = valueSql.Substring(0, valueSql.IndexOf("]", StringComparison.CurrentCultureIgnoreCase) + 1); valueSql = valueSql.Replace(tagToReplace, "B"); } #endif destinationValues.Add(new Tuple <string, object>(columnName, Expression.Constant(valueSql))); } else { destinationValues.Add(new Tuple <string, object>(columnName, value.Value ?? DBNull.Value)); } } return(destinationValues); }
public static IQueryable <TEntity> TreeQuery <TEntity, TKey>(string invariantName, IQueryable <TEntity> query, IEntityType entityType, Expression <Func <TEntity, bool> > startQuery, Expression <Func <TEntity, bool> > whereQuery = null, bool upSearch = false, string orderByProperty = null, int level = 0, bool distinct = false) where TEntity : class, IEntity <TKey> //ITreeEntity<TKey> //where TKey : struct, IEquatable<TKey> { var tableAnnn = entityType.FindAnnotation("Relational:TableName"); string tableName = tableAnnn?.Value.ToString(); var anno = entityType.FindProperty(nameof(ITreeEntity <int> .Pid)).FindAnnotation("Relational:ColumnName"); string parentFieldName = anno != null?anno.Value.ToString() : nameof(ITreeEntity <int> .Pid); var idAnno = entityType.FindProperty(nameof(ITreeEntity <int> .Id)).FindAnnotation("Relational:ColumnName"); string fieldName = idAnno != null?idAnno.Value.ToString() : nameof(ITreeEntity <int> .Id); string firstQuery = query.Where(startQuery).ToSql().Replace(Environment.NewLine, " "); string startQueryParament = startQuery.Parameters[0].Name; bool forNpgsql = IsNpgSql(invariantName); string orderByFieldName = null; if (!string.IsNullOrEmpty(orderByProperty)) { var orderByAnno = entityType.FindProperty(orderByProperty).FindAnnotation("Relational:ColumnName"); orderByFieldName = orderByAnno != null?orderByAnno.Value.ToString() : string.Format("\"{0}\"", orderByProperty); //forNpgsql = invariantName == "Npgsql.EntityFrameworkCore.PostgreSQL"; } if (forNpgsql && !string.IsNullOrEmpty(orderByFieldName)) { firstQuery = firstQuery.Insert(firstQuery.IndexOf(" FROM", StringComparison.CurrentCultureIgnoreCase), string.Format(", 0 As level, array[\"{0}\".\"{1}\"] as sorder", startQueryParament, orderByFieldName)); } else { firstQuery = firstQuery.Insert(firstQuery.IndexOf(" FROM", StringComparison.CurrentCultureIgnoreCase), ", 0 As level"); } string secondQuery = null; string thirdQuery = null; string whereQueryParament = tableName.Substring(0, 1).ToLower(); if (whereQuery == null) { secondQuery = query.ToSql().Replace(Environment.NewLine, " "); thirdQuery = secondQuery; if (forNpgsql && !string.IsNullOrEmpty(orderByFieldName)) { secondQuery = secondQuery.Insert(secondQuery.IndexOf(" FROM", StringComparison.CurrentCultureIgnoreCase), string.Format(", mytree.level + 1, sorder || \"{0}\".\"{1}\" as sorder", whereQueryParament, orderByFieldName)); } else { secondQuery = secondQuery.Insert(secondQuery.IndexOf(" FROM", StringComparison.CurrentCultureIgnoreCase), ", mytree.level + 1"); } if (upSearch) { secondQuery += string.Format(" join mytree on \"{0}\".\"{1}\" = \"mytree\".\"{2}\" ", whereQueryParament, fieldName, parentFieldName); } else { secondQuery += string.Format(" join mytree on \"{0}\".\"{1}\" = \"mytree\".\"{2}\" ", whereQueryParament, parentFieldName, fieldName); } } else { secondQuery = query.Where(whereQuery).ToSql().Replace(Environment.NewLine, " "); thirdQuery = secondQuery; whereQueryParament = startQuery.Parameters[0].Name; if (whereQueryParament == startQueryParament) { if (forNpgsql) { string forReplace = startQueryParament + "."; whereQueryParament += startQueryParament; string toReplace = whereQueryParament + "."; secondQuery = secondQuery.Replace(forReplace, toReplace); secondQuery = secondQuery.Replace("AS " + startQueryParament, "AS " + whereQueryParament); } else { string forReplace = "\"" + startQueryParament + "\""; whereQueryParament += startQueryParament; string toReplace = "\"" + whereQueryParament + "\""; secondQuery = secondQuery.Replace(forReplace, toReplace); } } if (forNpgsql) { secondQuery = secondQuery.Insert(secondQuery.IndexOf(" FROM", StringComparison.CurrentCultureIgnoreCase), string.Format(", mytree.level + 1, sorder || \"{0}\".\"{1}\" as sorder", whereQueryParament, orderByFieldName)); } else { secondQuery = secondQuery.Insert(secondQuery.IndexOf(" FROM", StringComparison.CurrentCultureIgnoreCase), ", mytree.level + 1"); } if (upSearch) { secondQuery = secondQuery.Insert(secondQuery.IndexOf(" WHERE", StringComparison.CurrentCultureIgnoreCase), string.Format(" join mytree on \"{0}\".\"{1}\" = \"mytree\".\"{2}\" ", whereQueryParament, fieldName, parentFieldName)); } else { secondQuery = secondQuery.Insert(secondQuery.IndexOf(" WHERE", StringComparison.CurrentCultureIgnoreCase), string.Format(" join mytree on \"{0}\".\"{1}\" = \"mytree\".\"{2}\" ", whereQueryParament, parentFieldName, fieldName)); } } StringBuilder sqlBuilder = new StringBuilder(); sqlBuilder.Append("with recursive mytree as ( "); sqlBuilder.Append(firstQuery); sqlBuilder.Append(" union all "); sqlBuilder.Append(secondQuery); if (!forNpgsql) { sqlBuilder.Append(" order by level desc"); if (!string.IsNullOrEmpty(orderByFieldName)) { //var orderByAnno = entityType.FindProperty(orderByProperty).FindAnnotation("Relational:ColumnName"); //string orderByFieldName = orderByAnno!=null? orderByAnno.Value.ToString() : string.Format("\"{0}\"", orderByProperty); sqlBuilder.Append(string.Format(", {0}", orderByFieldName)); } } sqlBuilder.Append(") "); if (distinct) { thirdQuery = thirdQuery.Replace("SELECT", "SELECT DISTINCT"); } thirdQuery = thirdQuery.Replace(tableName, "mytree"); sqlBuilder.Append(thirdQuery); if (level > 0) { if (whereQuery == null) { sqlBuilder.Append(" where "); } else { sqlBuilder.Append(" and "); } sqlBuilder.Append(string.Format("level = {0}", level)); } if (forNpgsql && !string.IsNullOrEmpty(orderByFieldName)) { sqlBuilder.Append(" order by sorder"); } return(query.FromSql(sqlBuilder.ToString())); }
public static IQueryable <TResult> TreeQuery <TEntity, TKey, TResult>(IRepositoryHelper repositoryHelper, IQueryable <TEntity> query, IEntityType entityType, Expression <Func <TEntity, bool> > startQuery, Expression <Func <TEntity, TResult> > selector, Expression <Func <TEntity, bool> > whereQuery = null, bool upSearch = false, string orderByProperty = null, int level = 0, bool distinct = false) where TEntity : class, IEntity <TKey> //ITreeEntity<TKey> where TResult : class //where TKey : struct, IEquatable<TKey> { var tableAnnn = entityType.FindAnnotation("Relational:TableName"); string tableName = tableAnnn?.Value.ToString(); var anno = entityType.FindProperty(nameof(ITreeEntity.Pid)).FindAnnotation("Relational:ColumnName"); string parentFieldName = anno != null?anno.Value.ToString() : nameof(ITreeEntity <int> .Pid); var idAnno = entityType.FindProperty(nameof(ITreeEntity.Id)).FindAnnotation("Relational:ColumnName"); string fieldName = idAnno != null?idAnno.Value.ToString() : nameof(ITreeEntity <int> .Id); List <DbParameter> dbParameters = new List <DbParameter>(); SqlWithParameters firstSqls = query.Where(startQuery).Select(selector).GetSqlTextWithParement();; AddDbParameter(repositoryHelper, dbParameters, firstSqls); string firstQuery = firstSqls.Sql.Replace(Environment.NewLine, " "); string startQueryParament = startQuery.Parameters[0].Name; bool forNpgsql = IsNpgSql(repositoryHelper?.ProviderName); string orderByFieldName = null; if (!string.IsNullOrEmpty(orderByProperty)) { var orderByAnno = entityType.FindProperty(orderByProperty).FindAnnotation("Relational:ColumnName"); orderByFieldName = orderByAnno != null?orderByAnno.Value.ToString() : string.Format("\"{0}\"", orderByProperty); //forNpgsql = repositoryHelper.ProviderName == "Npgsql.EntityFrameworkCore.PostgreSQL"; } if (forNpgsql && !string.IsNullOrEmpty(orderByFieldName)) { firstQuery = firstQuery.Insert(firstQuery.IndexOf(" FROM", StringComparison.CurrentCultureIgnoreCase), string.Format(", 0 As level, array[\"{0}\".\"{1}\"] as sorder", startQueryParament, orderByFieldName)); } else { firstQuery = firstQuery.Insert(firstQuery.IndexOf(" FROM", StringComparison.CurrentCultureIgnoreCase), ", 0 As level"); } //with recursive mytree as ( //select "t"."id", "t"."createtime", "t"."creator", "t"."customdata", "t"."displayname", "t"."group", "t"."icon", "t"."isenabled", "t"."isvisible", "t"."lastmodifytime", "t"."modifier", "t"."name", "t"."pid", "t"."platsupport", "t"."requiredpermissionname", "t"."requiresauthentication", "t"."sindex", "t"."target", "t"."url", 0 as level, ARRAY[t.sindex] as sorder from "menus" as "t" where "t"."pid" is null //union all //select "tt"."id", "tt"."createtime", "tt"."creator", "tt"."customdata", "tt"."displayname", "tt"."group", "tt"."icon", "tt"."isenabled", "tt"."isvisible", "tt"."lastmodifytime", "tt"."modifier", "tt"."name", "tt"."pid", "tt"."platsupport", "tt"."requiredpermissionname", "tt"."requiresauthentication", "tt"."sindex", "tt"."target", "tt"."url", mytree.level + 1, sorder || tt.sindex as sorder from "menus" as "tt" join mytree on "tt"."pid" = "mytree"."id" where "tt"."group" = 0 //) //select * from "mytree" as "t" where "t"."group" = 0 ORDER BY SORDER string secondQuery = null; string thirdQuery = null; string whereQueryParament = tableName.Substring(0, 1).ToLower(); if (whereQuery == null) { secondQuery = query.Select(selector).ToSql().Replace(Environment.NewLine, " "); whereQueryParament = selector.Parameters[0].Name; thirdQuery = secondQuery; if (forNpgsql && !string.IsNullOrEmpty(orderByFieldName)) { secondQuery = secondQuery.Insert(secondQuery.IndexOf(" FROM", StringComparison.CurrentCultureIgnoreCase), string.Format(", mytree.level + 1, sorder || \"{0}\".\"{1}\" as sorder", whereQueryParament, orderByFieldName)); } else { secondQuery = secondQuery.Insert(secondQuery.IndexOf(" FROM", StringComparison.CurrentCultureIgnoreCase), ", mytree.level + 1"); } if (upSearch) { secondQuery += string.Format(" join mytree on \"{0}\".\"{1}\" = \"mytree\".\"{2}\" ", whereQueryParament, fieldName, parentFieldName); } else { secondQuery += string.Format(" join mytree on \"{0}\".\"{1}\" = \"mytree\".\"{2}\" ", whereQueryParament, parentFieldName, fieldName); } } else { SqlWithParameters secondSqls = secondSqls = query.Where(whereQuery).Select(selector).GetSqlTextWithParement(); AddDbParameter(repositoryHelper, dbParameters, secondSqls); secondQuery = secondSqls.Sql.Replace(Environment.NewLine, " "); thirdQuery = secondQuery; whereQueryParament = whereQuery.Parameters[0].Name; if (whereQueryParament == startQueryParament) { if (forNpgsql) { string forReplace = startQueryParament + "."; whereQueryParament += startQueryParament; string toReplace = whereQueryParament + "."; secondQuery = secondQuery.Replace(forReplace, toReplace); secondQuery = secondQuery.Replace("AS " + startQueryParament, "AS " + whereQueryParament); } else { string forReplace = "\"" + startQueryParament + "\""; whereQueryParament += startQueryParament; string toReplace = "\"" + whereQueryParament + "\""; secondQuery = secondQuery.Replace(forReplace, toReplace); } } if (forNpgsql) { secondQuery = secondQuery.Insert(secondQuery.IndexOf(" FROM", StringComparison.CurrentCultureIgnoreCase), string.Format(", mytree.level + 1, sorder || \"{0}\".\"{1}\" as sorder", whereQueryParament, orderByFieldName)); } else { secondQuery = secondQuery.Insert(secondQuery.IndexOf(" FROM", StringComparison.CurrentCultureIgnoreCase), ", mytree.level + 1"); } if (upSearch) { secondQuery = secondQuery.Insert(secondQuery.IndexOf(" WHERE", StringComparison.CurrentCultureIgnoreCase), string.Format(" join mytree on \"{0}\".\"{1}\" = \"mytree\".\"{2}\" ", whereQueryParament, fieldName, parentFieldName)); } else { secondQuery = secondQuery.Insert(secondQuery.IndexOf(" WHERE", StringComparison.CurrentCultureIgnoreCase), string.Format(" join mytree on \"{0}\".\"{1}\" = \"mytree\".\"{2}\" ", whereQueryParament, parentFieldName, fieldName)); } } StringBuilder sqlBuilder = new StringBuilder(); sqlBuilder.Append("with recursive mytree as ( "); sqlBuilder.Append(firstQuery); sqlBuilder.Append(" union all "); sqlBuilder.Append(secondQuery); if (!forNpgsql) { sqlBuilder.Append(" order by level desc"); if (!string.IsNullOrEmpty(orderByFieldName)) { //var orderByAnno = entityType.FindProperty(orderByProperty).FindAnnotation("Relational:ColumnName"); //string orderByFieldName = orderByAnno!=null? orderByAnno.Value.ToString() : string.Format("\"{0}\"", orderByProperty); sqlBuilder.Append(string.Format(", {0}", orderByFieldName)); } } sqlBuilder.Append(") "); if (distinct) { thirdQuery = thirdQuery.Replace("SELECT", "SELECT DISTINCT"); } thirdQuery = thirdQuery.Replace(tableName, "mytree"); sqlBuilder.Append(thirdQuery); if (level > 0) { if (whereQuery == null) { sqlBuilder.Append(" where "); } else { sqlBuilder.Append(" and "); } sqlBuilder.Append(string.Format("level = {0}", repositoryHelper.CreateParameterName("level"))); AddDbParameter(repositoryHelper, dbParameters, "level", level); } if (forNpgsql && !string.IsNullOrEmpty(orderByFieldName)) { sqlBuilder.Append(" order by sorder"); } //外部where // var pp = db.Database.GetDbConnection().CreateCommand().CreateParameter(); // pp.ParameterName ="tid"; // pp.Value = 1; return(query.Select(selector).FromSql(sqlBuilder.ToString(), dbParameters.ToArray())); }
/// <summary> /// Generates code for the annotations on an entity type. /// </summary> /// <param name="builderName"> The name of the builder variable. </param> /// <param name="entityType"> The entity type. </param> /// <param name="stringBuilder"> The builder code is added to. </param> protected virtual void GenerateEntityTypeAnnotations( [NotNull] string builderName, [NotNull] IEntityType entityType, [NotNull] IndentedStringBuilder stringBuilder) { Check.NotNull(builderName, nameof(builderName)); Check.NotNull(entityType, nameof(entityType)); Check.NotNull(stringBuilder, nameof(stringBuilder)); var annotations = entityType.GetAnnotations().ToList(); var tableNameAnnotation = annotations.FirstOrDefault(a => a.Name == RelationalAnnotationNames.TableName); var schemaAnnotation = annotations.FirstOrDefault(a => a.Name == RelationalAnnotationNames.Schema); var nonDefaultName = false; if (tableNameAnnotation?.Value != null || entityType.BaseType == null) { stringBuilder .AppendLine() .Append(builderName) .Append(".") .Append(nameof(RelationalEntityTypeBuilderExtensions.ToTable)) .Append("(") .Append(Code.Literal((string)tableNameAnnotation?.Value ?? entityType.Relational().TableName)); annotations.Remove(tableNameAnnotation); nonDefaultName = true; } if (schemaAnnotation?.Value != null) { stringBuilder .Append(",") .Append(Code.Literal((string)schemaAnnotation.Value)); annotations.Remove(schemaAnnotation); nonDefaultName = true; } if (nonDefaultName) { stringBuilder.AppendLine(");"); } var discriminatorPropertyAnnotation = annotations.FirstOrDefault(a => a.Name == RelationalAnnotationNames.DiscriminatorProperty); var discriminatorValueAnnotation = annotations.FirstOrDefault(a => a.Name == RelationalAnnotationNames.DiscriminatorValue); if ((discriminatorPropertyAnnotation ?? discriminatorValueAnnotation) != null) { stringBuilder .AppendLine() .Append(builderName) .Append(".") .Append(nameof(RelationalEntityTypeBuilderExtensions.HasDiscriminator)); if (discriminatorPropertyAnnotation?.Value != null) { var discriminatorProperty = entityType.FindProperty((string)discriminatorPropertyAnnotation.Value); var propertyClrType = FindValueConverter(discriminatorProperty)?.ProviderClrType .MakeNullable(discriminatorProperty.IsNullable) ?? discriminatorProperty.ClrType; stringBuilder .Append("<") .Append(Code.Reference(propertyClrType)) .Append(">(") .Append(Code.Literal((string)discriminatorPropertyAnnotation.Value)) .Append(")"); } else { stringBuilder .Append("()"); } if (discriminatorValueAnnotation?.Value != null) { var value = discriminatorValueAnnotation.Value; var discriminatorProperty = entityType.RootType().Relational().DiscriminatorProperty; if (discriminatorProperty != null) { var valueConverter = FindValueConverter(discriminatorProperty); if (valueConverter != null) { value = valueConverter.ConvertToProvider(value); } } stringBuilder .Append(".") .Append(nameof(DiscriminatorBuilder.HasValue)) .Append("(") .Append(Code.UnknownLiteral(value)) .Append(")"); } stringBuilder.AppendLine(";"); annotations.Remove(discriminatorPropertyAnnotation); annotations.Remove(discriminatorValueAnnotation); } IgnoreAnnotations( annotations, RelationshipDiscoveryConvention.NavigationCandidatesAnnotationName, RelationshipDiscoveryConvention.AmbiguousNavigationsAnnotationName, InversePropertyAttributeConvention.InverseNavigationsAnnotationName, CoreAnnotationNames.NavigationAccessMode, CoreAnnotationNames.PropertyAccessMode, CoreAnnotationNames.ConstructorBinding); if (annotations.Count > 0) { foreach (var annotation in annotations) { stringBuilder .AppendLine() .Append(builderName); GenerateAnnotation(annotation, stringBuilder); stringBuilder .AppendLine(";"); } } }
protected virtual void GenerateEntityTypeAnnotations([NotNull] IEntityType entityType, [NotNull] IndentedStringBuilder stringBuilder) { Check.NotNull(entityType, nameof(entityType)); Check.NotNull(stringBuilder, nameof(stringBuilder)); var annotations = entityType.GetAnnotations().ToList(); var tableNameAnnotation = annotations.FirstOrDefault(a => a.Name == RelationalFullAnnotationNames.Instance.TableName); var schemaAnnotation = annotations.FirstOrDefault(a => a.Name == RelationalFullAnnotationNames.Instance.Schema); stringBuilder .AppendLine() .AppendLine() .Append("b.") .Append(nameof(RelationalEntityTypeBuilderExtensions.ToTable)) .Append("(") .Append(_code.Literal((string)tableNameAnnotation?.Value ?? entityType.DisplayName())); annotations.Remove(tableNameAnnotation); if (schemaAnnotation?.Value != null) { stringBuilder .Append(",") .Append(_code.Literal((string)schemaAnnotation.Value)); annotations.Remove(schemaAnnotation); } stringBuilder.Append(");"); var discriminatorPropertyAnnotation = annotations.FirstOrDefault(a => a.Name == RelationalFullAnnotationNames.Instance.DiscriminatorProperty); var discriminatorValueAnnotation = annotations.FirstOrDefault(a => a.Name == RelationalFullAnnotationNames.Instance.DiscriminatorValue); if ((discriminatorPropertyAnnotation ?? discriminatorValueAnnotation) != null) { stringBuilder .AppendLine() .AppendLine() .Append("b.") .Append(nameof(RelationalEntityTypeBuilderExtensions.HasDiscriminator)); if (discriminatorPropertyAnnotation?.Value != null) { var propertyClrType = entityType.FindProperty((string)discriminatorPropertyAnnotation.Value)?.ClrType; stringBuilder .Append("<") .Append(_code.Reference(propertyClrType.UnwrapEnumType())) .Append(">(") .Append(_code.UnknownLiteral(discriminatorPropertyAnnotation.Value)) .Append(")"); } else { stringBuilder .Append("()"); } if (discriminatorValueAnnotation?.Value != null) { stringBuilder .Append(".") .Append(nameof(DiscriminatorBuilder.HasValue)) .Append("(") .Append(_code.UnknownLiteral(discriminatorValueAnnotation.Value)) .Append(")"); } stringBuilder.Append(";"); annotations.Remove(discriminatorPropertyAnnotation); annotations.Remove(discriminatorValueAnnotation); } if (annotations.Any()) { foreach (var annotation in annotations) { stringBuilder .AppendLine() .AppendLine() .Append("b"); GenerateAnnotation(annotation, stringBuilder); stringBuilder.Append(";"); } } }
public DocumentSource(IEntityType entityType, CosmosDatabase database) { _collectionId = entityType.Cosmos().ContainerName; _database = database; _idProperty = entityType.FindProperty(StoreKeyConvention.IdPropertyName); }
public List <Tuple <string, object> > GetInnerValues <T>(IQueryable <T> query, Expression <Func <T, T> > updateFactory, IEntityType entity) where T : class #endif { #if EF5 || EF6 // GET mapping var mapping = entity.Info.EntityTypeMapping.MappingFragment; #elif EFCORE #if DNXCORE50 Assembly assembly; try { assembly = Assembly.Load(new AssemblyName("EntityFramework.MicrosoftSqlServer, Version = 7.0.0.0, Culture = neutral, PublicKeyToken = adb9793829ddae60")); } catch (Exception) { throw new Exception(""); } if (assembly == null) { throw new Exception(""); } var type = assembly.GetType("Microsoft.Data.Entity.SqlServerMetadataExtensions"); var sqlServerPropertyMethod = type.GetMethod("SqlServer", new[] { typeof(IProperty) }); #else var assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(x => x.FullName == "EntityFramework.MicrosoftSqlServer, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60"); if (assembly == null) { throw new Exception(""); } var type = assembly.GetType("Microsoft.Data.Entity.SqlServerMetadataExtensions"); var sqlServerPropertyMethod = type.GetMethod("SqlServer", BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(IProperty) }, null); #endif #endif // GET updateFactory command var values = ResolveUpdateFromQueryDictValues(updateFactory); var destinationValues = new List <Tuple <string, object> >(); foreach (var value in values) { #if EF5 || EF6 // FIND the mapped column var column = mapping.ScalarProperties.Find(x => x.Name == value.Key); if (column == null) { throw new Exception("The destination column could not be found:" + value.Key); } var columnName = column.ColumnName; #elif EFCORE var property = entity.FindProperty(value.Key); var mappingProperty = sqlServerPropertyMethod.Invoke(null, new[] { property }); var columnNameProperty = mappingProperty.GetType().GetProperty("ColumnName", BindingFlags.Public | BindingFlags.Instance); var columnName = (string)columnNameProperty.GetValue(mappingProperty); #endif if (value.Value is Expression) { // Oops! the value is not resolved yet! ParameterExpression parameterExpression = null; ((Expression)value.Value).Visit((ParameterExpression p) => { if (p.Type == typeof(T)) { parameterExpression = p; } return(p); }); // GET the update value by creating a new select command Type[] typeArguments = { typeof(T), ((Expression)value.Value).Type }; var lambdaExpression = Expression.Lambda(((Expression)value.Value), parameterExpression); var selectExpression = Expression.Call( typeof(Queryable), "Select", typeArguments, Expression.Constant(query), lambdaExpression); var result = Expression.Lambda(selectExpression).Compile().DynamicInvoke(); #if EF5 || EF6 // GET the select command text var commandText = ((IQueryable)result).ToString(); // GET the 'value' part var valueSql = commandText.IndexOf("AS [value]" + Environment.NewLine + "FROM", StringComparison.InvariantCultureIgnoreCase) != -1 ? commandText.Substring(6, commandText.IndexOf("AS [value]" + Environment.NewLine + "FROM", StringComparison.InvariantCultureIgnoreCase) - 6) : commandText.Substring(6, commandText.IndexOf("FROM", StringComparison.InvariantCultureIgnoreCase) - 6); // Add the destination name valueSql = valueSql.Replace("AS [C1]", ""); valueSql = valueSql.Replace("[Extent1]", "B"); #elif EFCORE var command = ((IQueryable)result).CreateCommand(); var commandText = command.CommandText; #if DNXCORE50 // GET the 'value' part var valueSql = commandText.IndexOf("AS [value]" + Environment.NewLine + "FROM", StringComparison.CurrentCultureIgnoreCase) != -1 ? commandText.Substring(6, commandText.IndexOf("AS [value]" + Environment.NewLine + "FROM", StringComparison.CurrentCultureIgnoreCase) - 6) : commandText.Substring(6, commandText.IndexOf("FROM", StringComparison.CurrentCultureIgnoreCase) - 6); #else // GET the 'value' part var valueSql = commandText.IndexOf("AS [value]" + Environment.NewLine + "FROM", StringComparison.InvariantCultureIgnoreCase) != -1 ? commandText.Substring(6, commandText.IndexOf("AS [value]" + Environment.NewLine + "FROM", StringComparison.InvariantCultureIgnoreCase) - 6) : commandText.Substring(6, commandText.IndexOf("FROM", StringComparison.InvariantCultureIgnoreCase) - 6); #endif // Add the destination name valueSql = valueSql.Replace("[x]", "B"); #endif destinationValues.Add(new Tuple <string, object>(columnName, Expression.Constant(valueSql))); } else { destinationValues.Add(new Tuple <string, object>(columnName, value.Value ?? DBNull.Value)); } } return(destinationValues); }
// TODO: Consider optimizing/consolidating property/navigation lookup // Issue #635 private static IPropertyBase TryGetPropertyBase(IEntityType entityType, string propertyName) => (IPropertyBase)entityType.FindProperty(propertyName) ?? entityType.GetNavigations().FirstOrDefault(n => n.Name == propertyName);
private T FindTracked(object[] keyValues, out IReadOnlyList <IProperty> keyProperties) { var key = _entityType.FindPrimaryKey(); keyProperties = HarmonyDbSetExtensions.GetPKFieldNames <T>(_entityType).Select(name => _entityType.FindProperty(name)).ToList(); if (keyProperties.Count != keyValues.Length) { //we allow partial matches so we dont need to throw here } for (var i = 0; i < keyValues.Length; i++) { var valueType = keyValues[i].GetType(); var propertyType = keyProperties[i].ClrType; if (valueType != propertyType.UnwrapNullableType()) { throw new ArgumentException( string.Format("key part {0}:{1} was mismatched with {2}:{3}", i, typeof(T).ShortDisplayName(), valueType.ShortDisplayName(), propertyType.ShortDisplayName())); } } return(_stateManager.TryGetEntry(key, keyValues)?.Entity as T); }
private static void ValidateConverter(IEntityType entityType, string propertyName, Type converterType = null) { entityType.FindProperty(propertyName).GetValueConverter().Should().BeOfType(converterType ?? _testEnumConverterType); }
public List <Tuple <string, object> > GetInnerValues <T>(IQueryable <T> query, Expression <Func <T, T> > updateFactory, IEntityType entity) where T : class #endif { #if EF5 || EF6 // GET mapping var mapping = entity.Info.EntityTypeMapping.MappingFragment; #elif EFCORE var context = query.GetDbContext(); var databaseCreator = context.Database.GetService <IDatabaseCreator>(); var assembly = databaseCreator.GetType().GetTypeInfo().Assembly; var assemblyName = assembly.GetName().Name; MethodInfo dynamicProviderEntityType = null; MethodInfo dynamicProviderProperty = null; bool isSqlServer = false; bool isPostgreSQL = false; bool isMySql = false; bool isMySqlPomelo = false; bool isSQLite = false; if (assemblyName == "Microsoft.EntityFrameworkCore.SqlServer") { isSqlServer = true; var type = assembly.GetType("Microsoft.EntityFrameworkCore.SqlServerMetadataExtensions"); dynamicProviderEntityType = type.GetMethod("SqlServer", new[] { typeof(IEntityType) }); dynamicProviderProperty = type.GetMethod("SqlServer", new[] { typeof(IProperty) }); } else if (assemblyName == "Npgsql.EntityFrameworkCore.PostgreSQL") { isPostgreSQL = true; var type = assembly.GetType("Microsoft.EntityFrameworkCore.NpgsqlMetadataExtensions"); dynamicProviderEntityType = type.GetMethod("Npgsql", new[] { typeof(IEntityType) }); dynamicProviderProperty = type.GetMethod("Npgsql", new[] { typeof(IProperty) }); } else if (assemblyName == "MySql.Data.EntityFrameworkCore") { isMySql = true; var type = assembly.GetType("MySQL.Data.EntityFrameworkCore.MySQLMetadataExtensions"); dynamicProviderEntityType = type.GetMethod("MySQL", new[] { typeof(IEntityType) }); dynamicProviderProperty = type.GetMethod("MySQL", new[] { typeof(IProperty) }); } else if (assemblyName == "Pomelo.EntityFrameworkCore.MySql") { isMySqlPomelo = true; var type = assembly.GetType("Microsoft.EntityFrameworkCore.MySqlMetadataExtensions"); dynamicProviderEntityType = type.GetMethod("MySql", new[] { typeof(IEntityType) }); dynamicProviderProperty = type.GetMethod("MySql", new[] { typeof(IProperty) }); } else if (assemblyName == "Microsoft.EntityFrameworkCore.Sqlite") { isSQLite = true; // CHANGE all for this one? dynamicProviderEntityType = typeof(RelationalMetadataExtensions).GetMethod("Relational", new[] { typeof(IEntityType) }); dynamicProviderProperty = typeof(RelationalMetadataExtensions).GetMethod("Relational", new[] { typeof(IProperty) }); } else { throw new Exception(string.Format(ExceptionMessage.Unsupported_Provider, assemblyName)); } #endif // GET updateFactory command var values = ResolveUpdateFromQueryDictValues(updateFactory); var destinationValues = new List <Tuple <string, object> >(); int valueI = -1; foreach (var value in values) { valueI++; #if EF5 || EF6 // FIND the mapped column var column = mapping.ScalarProperties.Find(x => x.Name == value.Key); if (column == null) { throw new Exception("The destination column could not be found:" + value.Key); } var columnName = column.ColumnName; #elif EFCORE var property = entity.FindProperty(value.Key); var mappingProperty = dynamicProviderProperty.Invoke(null, new[] { property }); var columnNameProperty = mappingProperty.GetType().GetProperty("ColumnName", BindingFlags.Public | BindingFlags.Instance); var columnName = (string)columnNameProperty.GetValue(mappingProperty); #endif if (value.Value is Expression) { // Oops! the value is not resolved yet! ParameterExpression parameterExpression = null; ((Expression)value.Value).Visit((ParameterExpression p) => { if (p.Type == typeof(T)) { parameterExpression = p; } return(p); }); // GET the update value by creating a new select command Type[] typeArguments = { typeof(T), ((Expression)value.Value).Type }; var lambdaExpression = Expression.Lambda(((Expression)value.Value), parameterExpression); var selectExpression = Expression.Call( typeof(Queryable), "Select", typeArguments, Expression.Constant(query), lambdaExpression); var result = Expression.Lambda(selectExpression).Compile().DynamicInvoke(); #if EF5 || EF6 // GET the select command text var commandText = ((IQueryable)result).ToString(); var parameters = ((IQueryable)result).GetObjectQuery().Parameters; // GET the 'value' part var pos = commandText.IndexOf("AS [value]" + Environment.NewLine + "FROM", StringComparison.InvariantCultureIgnoreCase) != -1 ? commandText.IndexOf("AS [value]" + Environment.NewLine + "FROM", StringComparison.InvariantCultureIgnoreCase) - 6 : commandText.IndexOf(Environment.NewLine + " FROM", StringComparison.InvariantCultureIgnoreCase) != -1 ? commandText.IndexOf(Environment.NewLine + " FROM", StringComparison.InvariantCultureIgnoreCase) - 6 : commandText.IndexOf(Environment.NewLine + "FROM", StringComparison.InvariantCultureIgnoreCase) != -1 ? commandText.IndexOf(Environment.NewLine + "FROM", StringComparison.InvariantCultureIgnoreCase) - 6 : commandText.IndexOf("FROM", StringComparison.InvariantCultureIgnoreCase) - 6; var valueSql = commandText.Substring(6, pos); // Add the destination name valueSql = valueSql.Replace("AS [C1]", ""); valueSql = valueSql.Replace("AS `C1`", ""); var listReplace = new List <string>() { "[Extent1]", "[Extent2]", "[Extent3]", "[Extent4]", "[Extent5]", "[Extent6]", "[Extent7]", "[Extent8]", "[Extent9]", "[Filter1]", "[Filter2]", "[Filter3]", "[Filter4]", "[Filter5]", "[Filter6]", "`Extent1`", "`Extent2`", "`Extent3`", "`Extent4`", "`Extent5`", "`Extent6`", "`Extent7`", "`Extent8`", "`Extent9`", "`Filter1`", "`Filter2`", "`Filter3`", "`Filter4`", "`Filter5`", "`Filter6`", }; // Replace the first value found only! foreach (var itemReplace in listReplace) { if (valueSql.Contains(itemReplace)) { valueSql = valueSql.Replace(itemReplace, "B"); break; } } // CHECK if valueSql end with ' AS [XYZ]' if (valueSql.LastIndexOf('[') != -1 && valueSql.Substring(0, valueSql.LastIndexOf('[')).EndsWith(" AS ", StringComparison.InvariantCulture)) { valueSql = valueSql.Substring(0, valueSql.LastIndexOf('[') - 4); } if (valueSql.LastIndexOf('`') != -1 && valueSql.Substring(0, valueSql.LastIndexOf('`')).EndsWith(" AS ", StringComparison.InvariantCulture)) { valueSql = valueSql.Substring(0, valueSql.LastIndexOf('`') - 4); } #elif EFCORE RelationalQueryContext queryContext; var command = ((IQueryable)result).CreateCommand(out queryContext); var commandText = command.CommandText; #if NETSTANDARD1_3 // GET the 'value' part var pos = commandText.IndexOf("AS [value]" + Environment.NewLine + "FROM", StringComparison.CurrentCultureIgnoreCase) != -1 ? commandText.IndexOf("AS [value]" + Environment.NewLine + "FROM", StringComparison.CurrentCultureIgnoreCase) - 6 : commandText.IndexOf(Environment.NewLine + " FROM", StringComparison.CurrentCultureIgnoreCase) != -1 ? commandText.IndexOf(Environment.NewLine + " FROM", StringComparison.CurrentCultureIgnoreCase) - 6 : commandText.IndexOf(Environment.NewLine + "FROM", StringComparison.CurrentCultureIgnoreCase) != -1 ? commandText.IndexOf(Environment.NewLine + "FROM", StringComparison.CurrentCultureIgnoreCase) - 6 : commandText.IndexOf("FROM", StringComparison.CurrentCultureIgnoreCase) - 6; var valueSql = commandText.Substring(6, pos); #else // GET the 'value' part var pos = commandText.IndexOf("AS [value]" + Environment.NewLine + "FROM", StringComparison.InvariantCultureIgnoreCase) != -1 ? commandText.IndexOf("AS [value]" + Environment.NewLine + "FROM", StringComparison.InvariantCultureIgnoreCase) - 6 : commandText.IndexOf(Environment.NewLine + " FROM", StringComparison.InvariantCultureIgnoreCase) != -1 ? commandText.IndexOf(Environment.NewLine + " FROM", StringComparison.InvariantCultureIgnoreCase) - 6 : commandText.IndexOf(Environment.NewLine + "FROM", StringComparison.InvariantCultureIgnoreCase) != -1 ? commandText.IndexOf(Environment.NewLine + "FROM", StringComparison.InvariantCultureIgnoreCase) - 6 : commandText.IndexOf("FROM", StringComparison.InvariantCultureIgnoreCase) - 6; var valueSql = commandText.Substring(6, pos); #endif valueSql = valueSql.Trim(); // Add the destination name valueSql = valueSql.Replace("[x]", "B"); valueSql = valueSql.Replace("[c]", "B"); if (valueSql.Length > 0 && valueSql[0] == '[' && valueSql.IndexOf("]", StringComparison.CurrentCultureIgnoreCase) != -1 && valueSql.IndexOf("]", StringComparison.CurrentCultureIgnoreCase) == valueSql.IndexOf("].[", StringComparison.CurrentCultureIgnoreCase) ) { // Could contains [something].[column] // GET the tag var tagToReplace = valueSql.Substring(0, valueSql.IndexOf("]", StringComparison.CurrentCultureIgnoreCase) + 1); valueSql = valueSql.Replace(tagToReplace, "B"); } #endif #if EF5 || EF6 foreach (var additionalParameter in parameters) { var newName = additionalParameter.Name + "_" + valueI; var newParameter = new ObjectParameter(newName, additionalParameter.Value); destinationValues.Add(new Tuple <string, object>(columnName, newParameter)); valueSql = valueSql.Replace(additionalParameter.Name, newName); } // TODO: For EF Core? #endif destinationValues.Add(new Tuple <string, object>(columnName, Expression.Constant(valueSql))); } else { destinationValues.Add(new Tuple <string, object>(columnName, value.Value ?? DBNull.Value)); } } return(destinationValues); }
private static IPropertyBase TryGetPropertyBase(IEntityType entityType, string propertyName) => (IPropertyBase)entityType.FindProperty(propertyName) ?? entityType.FindNavigation(propertyName);
/// <summary> /// Extract property metadata from the match expression /// </summary> /// <typeparam name="TEntity">Type of the entity being upserted</typeparam> /// <param name="entityType">Metadata type of the entity being upserted</param> /// <param name="matchExpression">The match expression provided by the user</param> /// <returns>A list of model properties used to match entities</returns> protected List <IProperty> ProcessMatchExpression <TEntity>(IEntityType entityType, Expression <Func <TEntity, object> > matchExpression) { List <IProperty> joinColumns; if (matchExpression is null) { joinColumns = entityType.GetProperties() .Where(p => p.IsKey()) .ToList(); } else if (matchExpression.Body is NewExpression newExpression) { joinColumns = new List <IProperty>(); foreach (MemberExpression arg in newExpression.Arguments) { if (arg == null || !(arg.Member is PropertyInfo) || !typeof(TEntity).Equals(arg.Expression.Type)) { throw new InvalidOperationException("Match columns have to be properties of the TEntity class"); } var property = entityType.FindProperty(arg.Member.Name); if (property == null) { throw new InvalidOperationException("Unknown property " + arg.Member.Name); } joinColumns.Add(property); } } else if (matchExpression.Body is UnaryExpression unaryExpression) { if (!(unaryExpression.Operand is MemberExpression memberExp) || !(memberExp.Member is PropertyInfo) || !typeof(TEntity).Equals(memberExp.Expression.Type)) { throw new InvalidOperationException("Match columns have to be properties of the TEntity class"); } var property = entityType.FindProperty(memberExp.Member.Name); joinColumns = new List <IProperty> { property }; } else if (matchExpression.Body is MemberExpression memberExpression) { if (!typeof(TEntity).Equals(memberExpression.Expression.Type) || !(memberExpression.Member is PropertyInfo)) { throw new InvalidOperationException("Match columns have to be properties of the TEntity class"); } var property = entityType.FindProperty(memberExpression.Member.Name); joinColumns = new List <IProperty> { property }; } else { throw new ArgumentException("match must be an anonymous object initialiser", nameof(matchExpression)); } if (joinColumns.All(p => p.ValueGenerated != ValueGenerated.Never)) { throw new InvalidMatchColumnsException(); } return(joinColumns); }
/// <summary> /// Extract property metadata from the match expression /// </summary> /// <typeparam name="TEntity">Type of the entity being upserted</typeparam> /// <param name="entityType">Metadata type of the entity being upserted</param> /// <param name="matchExpression">The match expression provided by the user</param> /// <param name="queryOptions">Options for the current query that will affect it's behaviour</param> /// <returns>A list of model properties used to match entities</returns> protected static ICollection <IProperty> ProcessMatchExpression <TEntity>(IEntityType entityType, Expression <Func <TEntity, object> >?matchExpression, RunnerQueryOptions queryOptions) { if (entityType == null) { throw new ArgumentNullException(nameof(entityType)); } List <IProperty> joinColumns; if (matchExpression is null) { joinColumns = entityType.GetProperties() .Where(p => p.IsKey()) .ToList(); } else if (matchExpression.Body is NewExpression newExpression) { joinColumns = new List <IProperty>(); foreach (MemberExpression arg in newExpression.Arguments) { if (arg == null || arg.Member is not PropertyInfo || !typeof(TEntity).Equals(arg.Expression?.Type)) { throw new InvalidOperationException(Resources.MatchColumnsHaveToBePropertiesOfTheTEntityClass); } var property = entityType.FindProperty(arg.Member.Name); if (property == null) { throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, Resources.UnknownProperty, arg.Member.Name)); } joinColumns.Add(property); } } else if (matchExpression.Body is UnaryExpression unaryExpression) { if (unaryExpression.Operand is not MemberExpression memberExp || memberExp.Member is not PropertyInfo || !typeof(TEntity).Equals(memberExp.Expression?.Type)) { throw new InvalidOperationException(Resources.MatchColumnsHaveToBePropertiesOfTheTEntityClass); } var property = entityType.FindProperty(memberExp.Member.Name); if (property == null) { throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, Resources.UnknownProperty, memberExp.Member.Name)); } joinColumns = new List <IProperty> { property }; } else if (matchExpression.Body is MemberExpression memberExpression) { if (!typeof(TEntity).Equals(memberExpression.Expression?.Type) || memberExpression.Member is not PropertyInfo) { throw new InvalidOperationException(Resources.MatchColumnsHaveToBePropertiesOfTheTEntityClass); } var property = entityType.FindProperty(memberExpression.Member.Name); if (property == null) { throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, Resources.UnknownProperty, memberExpression.Member.Name)); } joinColumns = new List <IProperty> { property }; } else { throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, Resources.ArgumentMustBeAnAnonymousObjectInitialiser, "match"), nameof(matchExpression)); } if (!queryOptions.AllowIdentityMatch && joinColumns.Any(p => p.ValueGenerated != ValueGenerated.Never)) { throw new InvalidMatchColumnsException(); } return(joinColumns); }
/// <summary> /// Generates code for the annotations on an entity type. /// </summary> /// <param name="builderName"> The name of the builder variable. </param> /// <param name="entityType"> The entity type. </param> /// <param name="stringBuilder"> The builder code is added to. </param> protected virtual void GenerateEntityTypeAnnotations( [NotNull] string builderName, [NotNull] IEntityType entityType, [NotNull] IndentedStringBuilder stringBuilder) { Check.NotNull(builderName, nameof(builderName)); Check.NotNull(entityType, nameof(entityType)); Check.NotNull(stringBuilder, nameof(stringBuilder)); var annotations = entityType.GetAnnotations().ToList(); var tableNameAnnotation = annotations.FirstOrDefault(a => a.Name == RelationalAnnotationNames.TableName); var schemaAnnotation = annotations.FirstOrDefault(a => a.Name == RelationalAnnotationNames.Schema); stringBuilder .AppendLine() .AppendLine() .Append(builderName) .Append(".") .Append(nameof(RelationalEntityTypeBuilderExtensions.ToTable)) .Append("(") .Append(Code.Literal((string)tableNameAnnotation?.Value ?? entityType.DisplayName())); annotations.Remove(tableNameAnnotation); if (schemaAnnotation?.Value != null) { stringBuilder .Append(",") .Append(Code.Literal((string)schemaAnnotation.Value)); annotations.Remove(schemaAnnotation); } stringBuilder.AppendLine(");"); var discriminatorPropertyAnnotation = annotations.FirstOrDefault(a => a.Name == RelationalAnnotationNames.DiscriminatorProperty); var discriminatorValueAnnotation = annotations.FirstOrDefault(a => a.Name == RelationalAnnotationNames.DiscriminatorValue); if ((discriminatorPropertyAnnotation ?? discriminatorValueAnnotation) != null) { stringBuilder .AppendLine() .Append(builderName) .Append(".") .Append(nameof(RelationalEntityTypeBuilderExtensions.HasDiscriminator)); if (discriminatorPropertyAnnotation?.Value != null) { var propertyClrType = entityType.FindProperty((string)discriminatorPropertyAnnotation.Value)?.ClrType; stringBuilder .Append("<") .Append(Code.Reference(propertyClrType.UnwrapEnumType())) .Append(">(") .Append(Code.UnknownLiteral(discriminatorPropertyAnnotation.Value)) .Append(")"); } else { stringBuilder .Append("()"); } if (discriminatorValueAnnotation?.Value != null) { stringBuilder .Append(".") .Append(nameof(DiscriminatorBuilder.HasValue)) .Append("(") .Append(Code.UnknownLiteral(discriminatorValueAnnotation.Value)) .Append(")"); } stringBuilder.AppendLine(";"); annotations.Remove(discriminatorPropertyAnnotation); annotations.Remove(discriminatorValueAnnotation); } IgnoreAnnotations( annotations, RelationshipDiscoveryConvention.NavigationCandidatesAnnotationName, RelationshipDiscoveryConvention.AmbiguousNavigationsAnnotationName, InversePropertyAttributeConvention.InverseNavigationsAnnotationName, CoreAnnotationNames.ConstructorBinding); if (annotations.Any()) { foreach (var annotation in annotations) { stringBuilder .AppendLine() .Append(builderName); GenerateAnnotation(annotation, stringBuilder); stringBuilder .Append(";") .AppendLine(); } } }
public string GetId(IUpdateEntry entry) => entry.GetCurrentValue <string>(_entityType.FindProperty(StoreKeyConvention.IdPropertyName));
private static IProperty GetProperty(IEntityType entityType, MemberIdentity memberIdentity) => memberIdentity.MemberInfo != null ? entityType.FindProperty(memberIdentity.MemberInfo) : entityType.FindProperty(memberIdentity.Name);
private static void ValidateTemporalPeriodProperty(IEntityType temporalEntityType, bool periodStart) { var annotationPropertyName = periodStart ? temporalEntityType.GetPeriodStartPropertyName() : temporalEntityType.GetPeriodEndPropertyName(); if (annotationPropertyName == null) { throw new InvalidOperationException( SqlServerStrings.TemporalMustDefinePeriodProperties( temporalEntityType.DisplayName())); } var periodProperty = temporalEntityType.FindProperty(annotationPropertyName); if (periodProperty == null) { throw new InvalidOperationException( SqlServerStrings.TemporalExpectedPeriodPropertyNotFound( temporalEntityType.DisplayName(), annotationPropertyName)); } if (!periodProperty.IsShadowProperty() && !temporalEntityType.IsPropertyBag) { throw new InvalidOperationException( SqlServerStrings.TemporalPeriodPropertyMustBeInShadowState( temporalEntityType.DisplayName(), periodProperty.Name)); } if (periodProperty.IsNullable || periodProperty.ClrType != typeof(DateTime)) { throw new InvalidOperationException( SqlServerStrings.TemporalPeriodPropertyMustBeNonNullableDateTime( temporalEntityType.DisplayName(), periodProperty.Name, nameof(DateTime))); } const string expectedPeriodColumnName = "datetime2"; if (periodProperty.GetColumnType() != expectedPeriodColumnName) { throw new InvalidOperationException( SqlServerStrings.TemporalPeriodPropertyMustBeMappedToDatetime2( temporalEntityType.DisplayName(), periodProperty.Name, expectedPeriodColumnName)); } if (periodProperty.TryGetDefaultValue(out var _)) { throw new InvalidOperationException( SqlServerStrings.TemporalPeriodPropertyCantHaveDefaultValue( temporalEntityType.DisplayName(), periodProperty.Name)); } if (temporalEntityType.GetTableName() is string tableName) { var storeObjectIdentifier = StoreObjectIdentifier.Table(tableName, temporalEntityType.GetSchema()); var periodColumnName = periodProperty.GetColumnName(storeObjectIdentifier); var propertiesMappedToPeriodColumn = temporalEntityType.GetProperties().Where( p => p.Name != periodProperty.Name && p.GetColumnName(storeObjectIdentifier) == periodColumnName).ToList(); foreach (var propertyMappedToPeriodColumn in propertiesMappedToPeriodColumn) { if (propertyMappedToPeriodColumn.ValueGenerated != ValueGenerated.OnAddOrUpdate) { throw new InvalidOperationException( SqlServerStrings.TemporalPropertyMappedToPeriodColumnMustBeValueGeneratedOnAddOrUpdate( temporalEntityType.DisplayName(), propertyMappedToPeriodColumn.Name, nameof(ValueGenerated.OnAddOrUpdate))); } if (propertyMappedToPeriodColumn.TryGetDefaultValue(out var _)) { throw new InvalidOperationException( SqlServerStrings.TemporalPropertyMappedToPeriodColumnCantHaveDefaultValue( temporalEntityType.DisplayName(), propertyMappedToPeriodColumn.Name)); } } } // TODO: check that period property is excluded from query (once the annotation is added) }
private void RunCore <TEntity>(DbContext dbContext, IEntityType entityType, ICollection <TEntity> entities, Expression <Func <TEntity, object> > matchExpression, Expression <Func <TEntity, TEntity, TEntity> > updateExpression, Expression <Func <TEntity, TEntity, bool> > updateCondition, bool noUpdate) where TEntity : class { // Find matching entities in the dbContext var matches = FindMatches(entityType, entities, dbContext, matchExpression); Action <TEntity, TEntity> updateAction = null; Func <TEntity, TEntity, bool> updateTest = updateCondition?.Compile(); if (updateExpression != null) { // If update expression is specified, create an update delegate based on that if (!(updateExpression.Body is MemberInitExpression entityUpdater)) { throw new ArgumentException("updater must be an Initialiser of the TEntity type", nameof(updateExpression)); } var properties = entityUpdater.Bindings.Select(b => b.Member).OfType <PropertyInfo>(); var updateFunc = updateExpression.Compile(); updateAction = (dbEntity, newEntity) => { var tmp = updateFunc(dbEntity, newEntity); foreach (var prop in properties) { var property = entityType.FindProperty(prop.Name); prop.SetValue(dbEntity, prop.GetValue(tmp) ?? property.GetDefaultValue()); } }; } else if (!noUpdate) { // Otherwise create a default update delegate that updates all non match, non auto generated columns var joinColumns = ProcessMatchExpression(entityType, matchExpression); var properties = entityType.GetProperties() .Where(p => p.ValueGenerated == ValueGenerated.Never) .Select(p => typeof(TEntity).GetProperty(p.Name)) .Where(p => p != null) .Except(joinColumns.Select(c => c.PropertyInfo)); updateAction = (dbEntity, newEntity) => { foreach (var prop in properties) { var property = entityType.FindProperty(prop.Name); prop.SetValue(dbEntity, prop.GetValue(newEntity) ?? property.GetDefaultValue()); } }; } foreach (var(dbEntity, newEntity) in matches) { if (dbEntity == null) { foreach (var prop in typeof(TEntity).GetProperties()) { if (prop.GetValue(newEntity) == null) { var property = entityType.FindProperty(prop.Name); if (property != null) { var defaultValue = property.GetDefaultValue(); if (defaultValue != null) { prop.SetValue(newEntity, defaultValue); } } } } dbContext.Add(newEntity); continue; } if (updateTest?.Invoke(dbEntity, newEntity) == false) { continue; } updateAction?.Invoke(dbEntity, newEntity); } }
private static Dictionary <IProperty, object> GetValues(this Driver driver, IEntityType entityType) { var result = new Dictionary <IProperty, object>(); result.Add(entityType.FindProperty("CarNumber"), driver.CarNumber); result.Add(entityType.FindProperty("Championships"), driver.Championships); result.Add(entityType.FindProperty("Id"), driver.Id); result.Add(entityType.FindProperty("FastestLaps"), driver.FastestLaps); result.Add(entityType.FindProperty("Name"), driver.Name); result.Add(entityType.FindProperty("Podiums"), driver.Podiums); result.Add(entityType.FindProperty("Poles"), driver.Poles); result.Add(entityType.FindProperty("Races"), driver.Races); result.Add(entityType.FindProperty("TeamId"), driver.TeamId); result.Add(entityType.FindProperty("Version"), driver.Version); result.Add(entityType.FindProperty("Wins"), driver.Wins); return(result); }