Browse Source

fix the issue when column name from database differ from property name from entity

Lith 10 months ago
parent
commit
39a9e23d85
25 changed files with 301 additions and 75 deletions
  1. 1 1
      src/Vitorm.MySql/SqlTranslateService.cs
  2. 7 1
      src/Vitorm.MySql/TranslateService/ExecuteUpdateTranslateService.cs
  3. 8 2
      src/Vitorm.SqlServer/SqlTranslate/ExecuteUpdateTranslateService.cs
  4. 1 1
      src/Vitorm.SqlServer/SqlTranslateService.cs
  5. 1 1
      src/Vitorm.Sqlite/SqlTranslateService.cs
  6. 10 4
      src/Vitorm.Sqlite/TranslateService/ExecuteUpdateTranslateService.cs
  7. 10 4
      src/Vitorm/Entity/DataAnnotations/ColumnDescriptor.cs
  8. 1 1
      src/Vitorm/Entity/DataAnnotations/EntityDescriptor.cs
  9. 3 3
      src/Vitorm/Entity/DataAnnotations/EntityLoader.cs
  10. 20 0
      src/Vitorm/Entity/Extensions/IEntityDescriptor_Extensions.cs
  11. 8 1
      src/Vitorm/Entity/IColumnDescriptor.cs
  12. 1 1
      src/Vitorm/Sql/DataReader/EntityReader/ModelReader.cs
  13. 1 1
      src/Vitorm/Sql/SqlDbContext.cs
  14. 31 9
      src/Vitorm/Sql/SqlTranslate/SqlTranslateService.cs
  15. 2 2
      src/Vitorm/StreamQuery/StreamReader.cs
  16. 31 0
      src/Vitorm/TypeUtil.cs
  17. 48 9
      test/Vitorm.MySql.MsTest/DataSource.cs
  18. 48 13
      test/Vitorm.SqlServer.MsTest/DataSource.cs
  19. 11 4
      test/Vitorm.Sqlite.MsTest/CommonTest/DbContext_Test.cs
  20. 2 2
      test/Vitorm.Sqlite.MsTest/CommonTest/Query_Group_Test.cs
  21. 2 2
      test/Vitorm.Sqlite.MsTest/CommonTest/Query_InnerJoin_ByJoin_Test.cs
  22. 2 2
      test/Vitorm.Sqlite.MsTest/CommonTest/Query_InnerJoin_BySelectMany_Test.cs
  23. 2 2
      test/Vitorm.Sqlite.MsTest/CommonTest/Query_LeftJoin_ByGroupJoin_Test.cs
  24. 6 3
      test/Vitorm.Sqlite.MsTest/CommonTest/Query_LeftJoin_BySelectMany_Test.cs
  25. 44 6
      test/Vitorm.Sqlite.MsTest/DataSource.cs

+ 1 - 1
src/Vitorm.MySql/SqlTranslateService.cs

@@ -188,7 +188,7 @@ CREATE TABLE {DelimitTableName(entityDescriptor)} (
             {
             {
                 var columnDbType = column.databaseType ?? GetColumnDbType(column.type);
                 var columnDbType = column.databaseType ?? GetColumnDbType(column.type);
                 // name varchar(100) DEFAULT NULL
                 // name varchar(100) DEFAULT NULL
-                return $"  {DelimitIdentifier(column.name)} {columnDbType} {(column.isNullable ? "DEFAULT NULL" : "NOT NULL")}";
+                return $"  {DelimitIdentifier(column.columnName)} {columnDbType} {(column.isNullable ? "DEFAULT NULL" : "NOT NULL")}";
             }
             }
         }
         }
         protected override string GetColumnDbType(Type type)
         protected override string GetColumnDbType(Type type)

+ 7 - 1
src/Vitorm.MySql/TranslateService/ExecuteUpdateTranslateService.cs

@@ -2,6 +2,8 @@
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Linq;
 using System.Linq;
 
 
+using Vit.Extensions.Vitorm_Extensions;
+
 using Vitorm.Sql.SqlTranslate;
 using Vitorm.Sql.SqlTranslate;
 using Vitorm.StreamQuery;
 using Vitorm.StreamQuery;
 
 
@@ -42,7 +44,11 @@ where t0.id = tmp.id ;
 
 
             var sqlToUpdateCols = columnsToUpdate
             var sqlToUpdateCols = columnsToUpdate
                 .Select(m => m.name)
                 .Select(m => m.name)
-                .Select(name => $"{NewLine}  {sqlTranslator.GetSqlField("t0", name)} = {sqlTranslator.GetSqlField("tmp", name)} ");
+                .Select(name =>
+                {
+                    var columnName = entityDescriptor.GetColumnNameByPropertyName(name);
+                    return $"{NewLine}  {sqlTranslator.GetSqlField("t0", columnName)} = {sqlTranslator.GetSqlField("tmp", name)} ";
+                });
 
 
             sql += string.Join(",", sqlToUpdateCols);
             sql += string.Join(",", sqlToUpdateCols);
 
 

+ 8 - 2
src/Vitorm.SqlServer/SqlTranslate/ExecuteUpdateTranslateService.cs

@@ -2,6 +2,8 @@
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Linq;
 using System.Linq;
 
 
+using Vit.Extensions.Vitorm_Extensions;
+
 using Vitorm.Sql.SqlTranslate;
 using Vitorm.Sql.SqlTranslate;
 using Vitorm.StreamQuery;
 using Vitorm.StreamQuery;
 
 
@@ -44,7 +46,11 @@ UPDATE [User]
 
 
             var sqlToUpdateCols = columnsToUpdate
             var sqlToUpdateCols = columnsToUpdate
                 .Select(m => m.name)
                 .Select(m => m.name)
-                .Select(name => $"{NewLine}  {sqlTranslator.DelimitIdentifier(name)} = {sqlTranslator.GetSqlField("tmp", name)} ");
+                .Select(name =>
+                {
+                    var columnName = entityDescriptor.GetColumnNameByPropertyName(name);
+                    return $"{NewLine}  {sqlTranslator.DelimitIdentifier(columnName)} = {sqlTranslator.GetSqlField("tmp", name)} ";
+                });
 
 
             sql += string.Join(",", sqlToUpdateCols);
             sql += string.Join(",", sqlToUpdateCols);
 
 
@@ -62,7 +68,7 @@ UPDATE [User]
         protected override string ReadSelect(QueryTranslateArgument arg, CombinedStream stream, string prefix = "select")
         protected override string ReadSelect(QueryTranslateArgument arg, CombinedStream stream, string prefix = "select")
         {
         {
             var entityDescriptor = arg.dbContext.GetEntityDescriptor(arg.resultEntityType);
             var entityDescriptor = arg.dbContext.GetEntityDescriptor(arg.resultEntityType);
-            var columnsToUpdate = (stream as StreamToUpdate) ?.fieldsToUpdate?.memberArgs;
+            var columnsToUpdate = (stream as StreamToUpdate)?.fieldsToUpdate?.memberArgs;
 
 
             if (columnsToUpdate?.Any() != true) throw new ArgumentException("can not get columns to update");
             if (columnsToUpdate?.Any() != true) throw new ArgumentException("can not get columns to update");
 
 

+ 1 - 1
src/Vitorm.SqlServer/SqlTranslateService.cs

@@ -199,7 +199,7 @@ CREATE TABLE {DelimitTableName(entityDescriptor)} (
             {
             {
                 var columnDbType = column.databaseType ?? GetColumnDbType(column.type);
                 var columnDbType = column.databaseType ?? GetColumnDbType(column.type);
                 // name varchar(100) DEFAULT NULL
                 // name varchar(100) DEFAULT NULL
-                return $"  {DelimitIdentifier(column.name)} {columnDbType} {(column.isNullable ? "DEFAULT NULL" : "NOT NULL")}";
+                return $"  {DelimitIdentifier(column.columnName)} {columnDbType} {(column.isNullable ? "DEFAULT NULL" : "NOT NULL")}";
             }
             }
         }
         }
 
 

+ 1 - 1
src/Vitorm.Sqlite/SqlTranslateService.cs

@@ -169,7 +169,7 @@ CREATE TABLE {DelimitTableName(entityDescriptor)} (
             {
             {
                 var columnDbType = column.databaseType ?? GetColumnDbType(column.type);
                 var columnDbType = column.databaseType ?? GetColumnDbType(column.type);
                 // name varchar(100) DEFAULT NULL
                 // name varchar(100) DEFAULT NULL
-                return $"  {DelimitIdentifier(column.name)} {columnDbType} {(column.isNullable ? "DEFAULT NULL" : "NOT NULL")}";
+                return $"  {DelimitIdentifier(column.columnName)} {columnDbType} {(column.isNullable ? "DEFAULT NULL" : "NOT NULL")}";
             }
             }
         }
         }
         protected override string GetColumnDbType(Type type)
         protected override string GetColumnDbType(Type type)

+ 10 - 4
src/Vitorm.Sqlite/TranslateService/ExecuteUpdateTranslateService.cs

@@ -2,6 +2,8 @@
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Linq;
 using System.Linq;
 
 
+using Vit.Extensions.Vitorm_Extensions;
+
 using Vitorm.Sql.SqlTranslate;
 using Vitorm.Sql.SqlTranslate;
 using Vitorm.StreamQuery;
 using Vitorm.StreamQuery;
 
 
@@ -47,7 +49,11 @@ UPDATE User SET name = 'u'||id  where id > 0;
 
 
             var sqlToUpdateCols = columnsToUpdate
             var sqlToUpdateCols = columnsToUpdate
                 .Select(m => m.name)
                 .Select(m => m.name)
-                .Select(name => $"{NewLine}  {sqlTranslator.DelimitIdentifier(name)} = (SELECT {sqlTranslator.DelimitIdentifier("_" + name)} FROM tmp WHERE tmp.{sqlTranslator.DelimitIdentifier(keyName)} = {sqlTranslator.DelimitTableName(entityDescriptor)}.{sqlTranslator.DelimitIdentifier(keyName)} )");
+                .Select(name =>
+                {
+                    var columnName = entityDescriptor.GetColumnNameByPropertyName(name);
+                    return $"{NewLine}  {sqlTranslator.DelimitIdentifier(columnName)} = (SELECT {sqlTranslator.DelimitIdentifier("_" + name)} FROM tmp WHERE tmp.{sqlTranslator.DelimitIdentifier(keyName)} = {sqlTranslator.DelimitTableName(entityDescriptor)}.{sqlTranslator.DelimitIdentifier(keyName)} )";
+                });
 
 
             sql += string.Join(",", sqlToUpdateCols);
             sql += string.Join(",", sqlToUpdateCols);
 
 
@@ -55,7 +61,7 @@ UPDATE User SET name = 'u'||id  where id > 0;
 
 
             return sql;
             return sql;
         }
         }
- 
+
 
 
         public ExecuteUpdateTranslateService(SqlTranslateService sqlTranslator) : base(sqlTranslator)
         public ExecuteUpdateTranslateService(SqlTranslateService sqlTranslator) : base(sqlTranslator)
         {
         {
@@ -64,7 +70,7 @@ UPDATE User SET name = 'u'||id  where id > 0;
         protected override string ReadSelect(QueryTranslateArgument arg, CombinedStream stream, string prefix = "select")
         protected override string ReadSelect(QueryTranslateArgument arg, CombinedStream stream, string prefix = "select")
         {
         {
             var entityDescriptor = arg.dbContext.GetEntityDescriptor(arg.resultEntityType);
             var entityDescriptor = arg.dbContext.GetEntityDescriptor(arg.resultEntityType);
-            var columnsToUpdate = (stream as StreamToUpdate) ?.fieldsToUpdate?.memberArgs;
+            var columnsToUpdate = (stream as StreamToUpdate)?.fieldsToUpdate?.memberArgs;
 
 
             if (columnsToUpdate?.Any() != true) throw new ArgumentException("can not get columns to update");
             if (columnsToUpdate?.Any() != true) throw new ArgumentException("can not get columns to update");
 
 
@@ -72,7 +78,7 @@ UPDATE User SET name = 'u'||id  where id > 0;
 
 
             foreach (var column in columnsToUpdate)
             foreach (var column in columnsToUpdate)
             {
             {
-                sqlFields.Add($"({sqlTranslator.EvalExpression( arg,  column.value)}) as {sqlTranslator.DelimitIdentifier("_" + column.name)}");
+                sqlFields.Add($"({sqlTranslator.EvalExpression(arg, column.value)}) as {sqlTranslator.DelimitIdentifier("_" + column.name)}");
             }
             }
 
 
             // primary key
             // primary key

+ 10 - 4
src/Vitorm/Entity/DataAnnotations/ColumnDescriptor.cs

@@ -5,12 +5,12 @@ namespace Vitorm.Entity.DataAnnotations
 {
 {
     public class ColumnDescriptor : IColumnDescriptor
     public class ColumnDescriptor : IColumnDescriptor
     {
     {
-        public ColumnDescriptor(PropertyInfo propertyInfo, string name, bool isKey, bool isIdentity, string databaseType, bool isNullable, int? columnOrder = null, bool? isIndex = null)
+        public ColumnDescriptor(PropertyInfo propertyInfo, string columnName, bool isKey, bool isIdentity, string databaseType, bool isNullable, int? columnOrder = null, bool? isIndex = null)
         {
         {
             this.propertyInfo = propertyInfo;
             this.propertyInfo = propertyInfo;
             type = propertyInfo.PropertyType;
             type = propertyInfo.PropertyType;
 
 
-            this.name = name;
+            this.columnName = columnName;
             this.isKey = isKey;
             this.isKey = isKey;
             this.isIdentity = isIdentity;
             this.isIdentity = isIdentity;
             this.databaseType = databaseType;
             this.databaseType = databaseType;
@@ -23,8 +23,14 @@ namespace Vitorm.Entity.DataAnnotations
         PropertyInfo propertyInfo;
         PropertyInfo propertyInfo;
         public Type type { get; private set; }
         public Type type { get; private set; }
 
 
-
-        public string name { get; private set; }
+        /// <summary>
+        /// property name in Entity Type
+        /// </summary>
+        public string propertyName => propertyInfo?.Name;
+        /// <summary>
+        /// column name in database
+        /// </summary>
+        public string columnName { get; private set; }
 
 
         public bool isKey { get; private set; }
         public bool isKey { get; private set; }
 
 

+ 1 - 1
src/Vitorm/Entity/DataAnnotations/EntityDescriptor.cs

@@ -24,7 +24,7 @@ namespace Vitorm.Entity.DataAnnotations
         /// <summary>
         /// <summary>
         /// primary key name
         /// primary key name
         /// </summary>
         /// </summary>
-        public string keyName => key?.name;
+        public string keyName => key?.columnName;
 
 
         /// <summary>
         /// <summary>
         /// primary key
         /// primary key

+ 3 - 3
src/Vitorm/Entity/DataAnnotations/EntityLoader.cs

@@ -39,9 +39,9 @@ namespace Vitorm.Entity.DataAnnotations
                  bool isKey = propertyInfo.GetCustomAttribute<System.ComponentModel.DataAnnotations.KeyAttribute>() != null;
                  bool isKey = propertyInfo.GetCustomAttribute<System.ComponentModel.DataAnnotations.KeyAttribute>() != null;
 
 
                  // #2 column name and type
                  // #2 column name and type
-                 string name; string databaseType; int? columnOrder;
+                 string columnName; string databaseType; int? columnOrder;
                  var columnAttr = propertyInfo.GetCustomAttribute<System.ComponentModel.DataAnnotations.Schema.ColumnAttribute>();
                  var columnAttr = propertyInfo.GetCustomAttribute<System.ComponentModel.DataAnnotations.Schema.ColumnAttribute>();
-                 name = columnAttr?.Name ?? propertyInfo.Name;
+                 columnName = columnAttr?.Name ?? propertyInfo.Name;
                  databaseType = columnAttr?.TypeName;
                  databaseType = columnAttr?.TypeName;
                  columnOrder = columnAttr?.Order;
                  columnOrder = columnAttr?.Order;
 
 
@@ -61,7 +61,7 @@ namespace Vitorm.Entity.DataAnnotations
                      }
                      }
                  }
                  }
 
 
-                 return new ColumnDescriptor(propertyInfo, name: name, isKey: isKey, isIdentity: isIdentity, databaseType: databaseType, isNullable: isNullable, columnOrder: columnOrder);
+                 return new ColumnDescriptor(propertyInfo, columnName: columnName, isKey: isKey, isIdentity: isIdentity, databaseType: databaseType, isNullable: isNullable, columnOrder: columnOrder);
              }).Where(column => column != null).ToArray();
              }).Where(column => column != null).ToArray();
 
 
             return new EntityDescriptor(entityType, allColumns, tableName, schema);
             return new EntityDescriptor(entityType, allColumns, tableName, schema);

+ 20 - 0
src/Vitorm/Entity/Extensions/IEntityDescriptor_Extensions.cs

@@ -0,0 +1,20 @@
+using System.Linq;
+
+using Vitorm.Entity;
+
+namespace Vit.Extensions.Vitorm_Extensions
+{
+    public static partial class IEntityDescriptor_Extensions
+    {
+        /// <summary>
+        /// get database column name by entity property name
+        /// </summary>
+        /// <param name="data"></param>
+        /// <param name="propertyName"></param>
+        /// <returns></returns>
+        public static string GetColumnNameByPropertyName(this IEntityDescriptor data, string propertyName)
+        {
+            return data?.allColumns.FirstOrDefault(m => m.propertyName == propertyName)?.columnName;
+        }
+    }
+}

+ 8 - 1
src/Vitorm/Entity/IColumnDescriptor.cs

@@ -5,7 +5,14 @@ namespace Vitorm.Entity
     public interface IColumnDescriptor
     public interface IColumnDescriptor
     {
     {
         Type type { get; }
         Type type { get; }
-        string name { get; }
+        /// <summary>
+        /// property name in Entity Type
+        /// </summary>
+        string propertyName { get; }
+        /// <summary>
+        /// column name in database
+        /// </summary>
+        string columnName { get; }
         bool isKey { get; }
         bool isKey { get; }
 
 
         /// <summary>
         /// <summary>

+ 1 - 1
src/Vitorm/Sql/DataReader/EntityReader/ModelReader.cs

@@ -33,7 +33,7 @@ namespace Vitorm.Sql.DataReader
             {
             {
                 foreach (var column in entityDescriptor.allColumns)
                 foreach (var column in entityDescriptor.allColumns)
                 {
                 {
-                    var sqlFieldName = sqlTranslator.GetSqlField(tableName, column.name);
+                    var sqlFieldName = sqlTranslator.GetSqlField(tableName, column.columnName);
                     proppertyReaders.Add(new EntityPropertyReader(entityReader, column, sqlFieldName));
                     proppertyReaders.Add(new EntityPropertyReader(entityReader, column, sqlFieldName));
                 }
                 }
             }
             }

+ 1 - 1
src/Vitorm/Sql/SqlDbContext.cs

@@ -215,7 +215,7 @@ namespace Vitorm.Sql
                 var entity = (Entity)Activator.CreateInstance(typeof(Entity));
                 var entity = (Entity)Activator.CreateInstance(typeof(Entity));
                 foreach (var column in entityDescriptor.allColumns)
                 foreach (var column in entityDescriptor.allColumns)
                 {
                 {
-                    var value = TypeUtil.ConvertToType(reader[column.name], column.type);
+                    var value = TypeUtil.ConvertToType(reader[column.columnName], column.type);
                     if (value != null)
                     if (value != null)
                         column.SetValue(entity, value);
                         column.SetValue(entity, value);
                 }
                 }

+ 31 - 9
src/Vitorm/Sql/SqlTranslate/SqlTranslateService.cs

@@ -10,6 +10,8 @@ using System.Text;
 using System.Linq.Expressions;
 using System.Linq.Expressions;
 using static Vitorm.Sql.SqlDbContext;
 using static Vitorm.Sql.SqlDbContext;
 using System.Data;
 using System.Data;
+using Vit.Linq.ExpressionTree.ExpressionConvertor;
+using Vit.Extensions.Vitorm_Extensions;
 
 
 namespace Vitorm.Sql.SqlTranslate
 namespace Vitorm.Sql.SqlTranslate
 {
 {
@@ -67,7 +69,22 @@ namespace Vitorm.Sql.SqlTranslate
             if (string.IsNullOrWhiteSpace(memberName))
             if (string.IsNullOrWhiteSpace(memberName))
             {
             {
                 var entityType = member.Member_GetType();
                 var entityType = member.Member_GetType();
-                memberName = dbContext.GetEntityDescriptor(entityType)?.keyName;
+                var entityDescriptor = dbContext.GetEntityDescriptor(entityType);
+                memberName = entityDescriptor?.keyName;
+            }
+            else if (member.objectValue != null)
+            {
+                var entityType = member.objectValue.Member_GetType();
+                if (entityType != null)
+                {
+                    var entityDescriptor = dbContext.GetEntityDescriptor(entityType);
+                    if (entityDescriptor != null)
+                    {
+                        var columnName = entityDescriptor.GetColumnNameByPropertyName(memberName);
+                        if (string.IsNullOrEmpty(columnName)) throw new NotSupportedException("[QueryTranslator] can not find database column name for property : " + memberName);
+                        memberName = columnName;
+                    }
+                }
             }
             }
 
 
             // 1: {"nodeType":"Member","parameterName":"a0","memberName":"id"}
             // 1: {"nodeType":"Member","parameterName":"a0","memberName":"id"}
@@ -184,14 +201,19 @@ namespace Vitorm.Sql.SqlTranslate
                                 }
                                 }
                             case nameof(Enumerable.Max) or nameof(Enumerable.Min) or nameof(Enumerable.Sum) or nameof(Enumerable.Average) when methodCall.arguments.Length == 2:
                             case nameof(Enumerable.Max) or nameof(Enumerable.Min) or nameof(Enumerable.Sum) or nameof(Enumerable.Average) when methodCall.arguments.Length == 2:
                                 {
                                 {
-                                    var stream = methodCall.arguments[0] as ExpressionNode_Member;
-                                    if (stream?.nodeType != NodeType.Member) break;
+                                    var source = methodCall.arguments[0];
+                                    if (source?.nodeType != NodeType.Member) break;
+
+                                    var entityType = methodCall.MethodCall_GetParamTypes()[0].GetGenericArguments()[0];
+                                    source = TypeUtil.Clone(source).Member_SetType(entityType);
 
 
 
 
                                     var lambdaFieldSelect = methodCall.arguments[1] as ExpressionNode_Lambda;
                                     var lambdaFieldSelect = methodCall.arguments[1] as ExpressionNode_Lambda;
 
 
                                     var parameterName = lambdaFieldSelect.parameterNames[0];
                                     var parameterName = lambdaFieldSelect.parameterNames[0];
-                                    var parameterValue = (ExpressionNode)stream;
+                                    var parameterValue = source;
+
+
                                     Func<ExpressionNode_Member, ExpressionNode> GetParameter = (member) =>
                                     Func<ExpressionNode_Member, ExpressionNode> GetParameter = (member) =>
                                     {
                                     {
                                         if (member.nodeType == NodeType.Member && member.parameterName == parameterName)
                                         if (member.nodeType == NodeType.Member && member.parameterName == parameterName)
@@ -321,7 +343,7 @@ namespace Vitorm.Sql.SqlTranslate
                 var sqlParam = new Dictionary<string, object>();
                 var sqlParam = new Dictionary<string, object>();
                 foreach (var column in columns)
                 foreach (var column in columns)
                 {
                 {
-                    sqlParam[column.name] = column.GetValue(entity);
+                    sqlParam[column.columnName] = column.GetValue(entity);
                 }
                 }
                 return sqlParam;
                 return sqlParam;
             };
             };
@@ -332,8 +354,8 @@ namespace Vitorm.Sql.SqlTranslate
 
 
             foreach (var column in columns)
             foreach (var column in columns)
             {
             {
-                columnNames.Add(DelimitIdentifier(column.name));
-                valueParams.Add(GenerateParameterName(column.name));
+                columnNames.Add(DelimitIdentifier(column.columnName));
+                valueParams.Add(GenerateParameterName(column.columnName));
             }
             }
             #endregion
             #endregion
 
 
@@ -384,7 +406,7 @@ namespace Vitorm.Sql.SqlTranslate
                 var sqlParam = new Dictionary<string, object>();
                 var sqlParam = new Dictionary<string, object>();
                 foreach (var column in entityDescriptor.allColumns)
                 foreach (var column in entityDescriptor.allColumns)
                 {
                 {
-                    var columnName = column.name;
+                    var columnName = column.columnName;
                     var value = column.GetValue(entity);
                     var value = column.GetValue(entity);
 
 
                     sqlParam[columnName] = value;
                     sqlParam[columnName] = value;
@@ -398,7 +420,7 @@ namespace Vitorm.Sql.SqlTranslate
             string columnName;
             string columnName;
             foreach (var column in entityDescriptor.columns)
             foreach (var column in entityDescriptor.columns)
             {
             {
-                columnName = column.name;
+                columnName = column.columnName;
                 columnsToUpdate.Add($"{DelimitIdentifier(columnName)}={GenerateParameterName(columnName)}");
                 columnsToUpdate.Add($"{DelimitIdentifier(columnName)}={GenerateParameterName(columnName)}");
             }
             }
 
 

+ 2 - 2
src/Vitorm/StreamQuery/StreamReader.cs

@@ -10,11 +10,11 @@ namespace Vitorm.StreamQuery
 
 
     public class ExpressionNode_RenameableMember : ExpressionNode
     public class ExpressionNode_RenameableMember : ExpressionNode
     {
     {
-        private IStream stream;
+        protected IStream stream;
         public override string parameterName
         public override string parameterName
         {
         {
             get => stream?.alias;
             get => stream?.alias;
-            set => throw new NotSupportedException();
+            set { }
         }
         }
         public static ExpressionNode Member(IStream stream, Type memberType)
         public static ExpressionNode Member(IStream stream, Type memberType)
         {
         {

+ 31 - 0
src/Vitorm/TypeUtil.cs

@@ -1,4 +1,10 @@
 using System;
 using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Security.Cryptography;
+
+using Vit.Linq.ExpressionTree.ComponentModel;
 
 
 
 
 namespace Vitorm
 namespace Vitorm
@@ -52,6 +58,31 @@ namespace Vitorm
             return Activator.CreateInstance(type);
             return Activator.CreateInstance(type);
         }
         }
 
 
+        public static Model Clone<Model>(Model source)
+        {
+            if (null == source) return default;
+            var type = source.GetType();
+            var destination = (Model)Activator.CreateInstance(type);
+
+            foreach (var p in type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
+            {
+                if (p.CanRead && p.CanWrite)
+                {
+                    var value = p.GetValue(source);
+                    if (value == null) continue;
+                    p.SetValue(destination, value);
+                }
+            }
+            foreach (var p in type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
+            {
+                {
+                    var value = p.GetValue(source);
+                    if (value == null) continue;
+                    p.SetValue(destination, value);
+                }
+            }
+            return destination;
+        }
 
 
     }
     }
 }
 }

+ 48 - 9
test/Vitorm.MySql.MsTest/DataSource.cs

@@ -1,7 +1,6 @@
 using Vitorm.Sql;
 using Vitorm.Sql;
 using Vit.Extensions;
 using Vit.Extensions;
 using Vit.Core.Util.ConfigurationManager;
 using Vit.Core.Util.ConfigurationManager;
-using System.ComponentModel.DataAnnotations.Schema;
 
 
 namespace Vitorm.MsTest
 namespace Vitorm.MsTest
 {
 {
@@ -9,13 +8,19 @@ namespace Vitorm.MsTest
     public class User
     public class User
     {
     {
         [System.ComponentModel.DataAnnotations.Key]
         [System.ComponentModel.DataAnnotations.Key]
-        [System.ComponentModel.DataAnnotations.Schema.DatabaseGenerated(DatabaseGeneratedOption.Identity)]
+        [System.ComponentModel.DataAnnotations.Schema.Column("userId")]
+        [System.ComponentModel.DataAnnotations.Schema.DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)]
         public int id { get; set; }
         public int id { get; set; }
+        [System.ComponentModel.DataAnnotations.Schema.Column("userName")]
         public string name { get; set; }
         public string name { get; set; }
+        [System.ComponentModel.DataAnnotations.Schema.Column("userBirth")]
         public DateTime? birth { get; set; }
         public DateTime? birth { get; set; }
-
+        [System.ComponentModel.DataAnnotations.Schema.Column("userFatherId")]
         public int? fatherId { get; set; }
         public int? fatherId { get; set; }
+        [System.ComponentModel.DataAnnotations.Schema.Column("userMotherId")]
         public int? motherId { get; set; }
         public int? motherId { get; set; }
+        [System.ComponentModel.DataAnnotations.Schema.Column("userClassId")]
+        public int? classId { get; set; }
 
 
         [System.ComponentModel.DataAnnotations.Schema.NotMapped]
         [System.ComponentModel.DataAnnotations.Schema.NotMapped]
         public string test { get; set; }
         public string test { get; set; }
@@ -29,6 +34,22 @@ namespace Vitorm.MsTest
         }
         }
     }
     }
 
 
+    [System.ComponentModel.DataAnnotations.Schema.Table("UserClass")]
+    public class UserClass
+    {
+        [System.ComponentModel.DataAnnotations.Key]
+        [System.ComponentModel.DataAnnotations.Schema.Column("classId")]
+        [System.ComponentModel.DataAnnotations.Schema.DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)]
+        public int id { get; set; }
+        [System.ComponentModel.DataAnnotations.Schema.Column("className")]
+        public string name { get; set; }
+
+        public static List<UserClass> NewClasses(int startId, int count = 1)
+        {
+            return Enumerable.Range(startId, count).Select(id => new UserClass { id = 0, name = "class" + id }).ToList();
+        }
+    }
+
 
 
     public class DataSource
     public class DataSource
     {
     {
@@ -44,11 +65,13 @@ namespace Vitorm.MsTest
 
 
             dbContext.BeginTransaction();
             dbContext.BeginTransaction();
 
 
-            dbContext.Execute(sql: "DROP TABLE  if exists `User`;");
+            #region #1 init User
+            {
+                dbContext.Execute(sql: "DROP TABLE if exists `User`;");
 
 
-            dbContext.Create<User>();
+                dbContext.Create<User>();
 
 
-            var users = new List<User> {
+                var users = new List<User> {
                     new User {   name="u146", fatherId=4, motherId=6 },
                     new User {   name="u146", fatherId=4, motherId=6 },
                     new User {   name="u246", fatherId=4, motherId=6 },
                     new User {   name="u246", fatherId=4, motherId=6 },
                     new User {   name="u356", fatherId=5, motherId=6 },
                     new User {   name="u356", fatherId=5, motherId=6 },
@@ -57,11 +80,27 @@ namespace Vitorm.MsTest
                     new User {   name="u600" },
                     new User {   name="u600" },
                 };
                 };
 
 
-            dbContext.AddRange(users);
+                dbContext.AddRange(users);
+
+                users.ForEach(user =>
+                {
+                    user.birth = DateTime.Parse("2021-01-01 00:00:00").AddHours(user.id);
+                    user.classId = user.id % 2 + 1;
+                });
+
+                dbContext.UpdateRange(users);
+            }
+            #endregion
+
+            #region #2 init Class
+            {
+                dbContext.Execute(sql: "DROP TABLE if exists `UserClass`;");
 
 
-            users.ForEach(user => { user.birth = DateTime.Parse("2021-01-01 00:00:00").AddHours(user.id); });
+                dbContext.Create<UserClass>();
+                dbContext.AddRange(UserClass.NewClasses(1, 6));
+            }
+            #endregion
 
 
-            dbContext.UpdateRange(users);
 
 
             return dbContext;
             return dbContext;
         }
         }

+ 48 - 13
test/Vitorm.SqlServer.MsTest/DataSource.cs

@@ -1,7 +1,6 @@
 using Vitorm.Sql;
 using Vitorm.Sql;
 using Vit.Extensions;
 using Vit.Extensions;
 using Vit.Core.Util.ConfigurationManager;
 using Vit.Core.Util.ConfigurationManager;
-using System.ComponentModel.DataAnnotations.Schema;
 
 
 namespace Vitorm.MsTest
 namespace Vitorm.MsTest
 {
 {
@@ -9,21 +8,24 @@ namespace Vitorm.MsTest
     public class User
     public class User
     {
     {
         [System.ComponentModel.DataAnnotations.Key]
         [System.ComponentModel.DataAnnotations.Key]
-        [System.ComponentModel.DataAnnotations.Schema.DatabaseGenerated(DatabaseGeneratedOption.Identity)]
-        [System.ComponentModel.DataAnnotations.Schema.Column("id", TypeName = "int")]
+        [System.ComponentModel.DataAnnotations.Schema.DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)]
+        [System.ComponentModel.DataAnnotations.Schema.Column("userId", TypeName = "int")]
         public int id { get; set; }
         public int id { get; set; }
 
 
-        [System.ComponentModel.DataAnnotations.Schema.Column("name", TypeName = "varchar(1000)")]
+        [System.ComponentModel.DataAnnotations.Schema.Column("userName", TypeName = "varchar(1000)")]
         [System.ComponentModel.DataAnnotations.Required]
         [System.ComponentModel.DataAnnotations.Required]
         public string name { get; set; }
         public string name { get; set; }
-     
+        [System.ComponentModel.DataAnnotations.Schema.Column("userBirth")]
         public DateTime? birth { get; set; }
         public DateTime? birth { get; set; }
-
+        [System.ComponentModel.DataAnnotations.Schema.Column("userFatherId")]
         public int? fatherId { get; set; }
         public int? fatherId { get; set; }
+        [System.ComponentModel.DataAnnotations.Schema.Column("userMotherId")]
         public int? motherId { get; set; }
         public int? motherId { get; set; }
+        [System.ComponentModel.DataAnnotations.Schema.Column("userClassId")]
+        public int? classId { get; set; }
 
 
         [System.ComponentModel.DataAnnotations.Schema.NotMapped]
         [System.ComponentModel.DataAnnotations.Schema.NotMapped]
-        public string test{ get; set; }
+        public string test { get; set; }
 
 
         public static User NewUser(int id, bool forAdd = false) => new User { id = forAdd ? 0 : id, name = "testUser" + id };
         public static User NewUser(int id, bool forAdd = false) => new User { id = forAdd ? 0 : id, name = "testUser" + id };
 
 
@@ -33,6 +35,22 @@ namespace Vitorm.MsTest
         }
         }
     }
     }
 
 
+    [System.ComponentModel.DataAnnotations.Schema.Table("UserClass")]
+    public class UserClass
+    {
+        [System.ComponentModel.DataAnnotations.Key]
+        [System.ComponentModel.DataAnnotations.Schema.Column("classId")]
+        [System.ComponentModel.DataAnnotations.Schema.DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)]
+        public int id { get; set; }
+        [System.ComponentModel.DataAnnotations.Schema.Column("className")]
+        public string name { get; set; }
+
+        public static List<UserClass> NewClasses(int startId, int count = 1)
+        {
+            return Enumerable.Range(startId, count).Select(id => new UserClass { id = 0, name = "class" + id }).ToList();
+        }
+    }
+
 
 
     public class DataSource
     public class DataSource
     {
     {
@@ -49,11 +67,13 @@ namespace Vitorm.MsTest
 
 
             dbContext.BeginTransaction();
             dbContext.BeginTransaction();
 
 
-            dbContext.Execute(sql: "IF OBJECT_ID(N'User', N'U') IS  NOT  NULL \r\nDROP TABLE [User];");
+            #region #1 init User
+            {
+                dbContext.Execute(sql: "IF OBJECT_ID(N'User', N'U') IS  NOT  NULL \r\nDROP TABLE [User];");
 
 
-            dbContext.Create<User>();
+                dbContext.Create<User>();
 
 
-            var users = new List<User> {
+                var users = new List<User> {
                     new User {   name="u146", fatherId=4, motherId=6 },
                     new User {   name="u146", fatherId=4, motherId=6 },
                     new User {   name="u246", fatherId=4, motherId=6 },
                     new User {   name="u246", fatherId=4, motherId=6 },
                     new User {   name="u356", fatherId=5, motherId=6 },
                     new User {   name="u356", fatherId=5, motherId=6 },
@@ -62,11 +82,26 @@ namespace Vitorm.MsTest
                     new User {   name="u600" },
                     new User {   name="u600" },
                 };
                 };
 
 
-            dbContext.AddRange(users);
+                dbContext.AddRange(users);
+
+                users.ForEach(user =>
+                {
+                    user.birth = DateTime.Parse("2021-01-01 00:00:00").AddHours(user.id);
+                    user.classId = user.id % 2 + 1;
+                });
+
+                dbContext.UpdateRange(users);
+            }
+            #endregion
 
 
-            users.ForEach(user => { user.birth = DateTime.Parse("2021-01-01 00:00:00").AddHours(user.id); });
+            #region #2 init Class
+            {
+                dbContext.Execute(sql: "IF OBJECT_ID(N'UserClass', N'U') IS  NOT  NULL \r\nDROP TABLE [UserClass];");
 
 
-            dbContext.UpdateRange(users);
+                dbContext.Create<UserClass>();
+                dbContext.AddRange(UserClass.NewClasses(1, 6));
+            }
+            #endregion
 
 
             return dbContext;
             return dbContext;
         }
         }

+ 11 - 4
test/Vitorm.Sqlite.MsTest/CommonTest/DbContext_Test.cs

@@ -6,6 +6,7 @@ using Vitorm.Entity;
 using Vitorm.Entity.DataAnnotations;
 using Vitorm.Entity.DataAnnotations;
 using Vitorm.Entity.Loader;
 using Vitorm.Entity.Loader;
 using Vitorm.Entity.LoaderAttribute;
 using Vitorm.Entity.LoaderAttribute;
+using Vit.Extensions.Vitorm_Extensions;
 
 
 namespace Vitorm.MsTest.CommonTest
 namespace Vitorm.MsTest.CommonTest
 {
 {
@@ -19,7 +20,7 @@ namespace Vitorm.MsTest.CommonTest
             var entityDescriptor = dbContext.GetEntityDescriptor(typeof(User));
             var entityDescriptor = dbContext.GetEntityDescriptor(typeof(User));
             var key = entityDescriptor.key;
             var key = entityDescriptor.key;
 
 
-            Assert.AreEqual("id", key.name);
+            Assert.AreEqual("userId", key.columnName);
         }
         }
 
 
 
 
@@ -31,6 +32,7 @@ namespace Vitorm.MsTest.CommonTest
             // #1 EntityLoaderAttribute
             // #1 EntityLoaderAttribute
             {
             {
                 var users = dbContext.Query<CustomUser2>().Where(m => m.name == "u146").ToList();
                 var users = dbContext.Query<CustomUser2>().Where(m => m.name == "u146").ToList();
+                var sql = dbContext.Query<CustomUser2>().Where(m => m.name == "u146").ToExecuteString();
                 Assert.AreEqual(1, users.Count());
                 Assert.AreEqual(1, users.Count());
                 Assert.AreEqual(1, users[0].id);
                 Assert.AreEqual(1, users[0].id);
             }
             }
@@ -61,15 +63,20 @@ namespace Vitorm.MsTest.CommonTest
         {
         {
             [Label("Key")]
             [Label("Key")]
             [Label("Identity")]
             [Label("Identity")]
+            [Property(name = "ColumnName", value = "userId")]
             public int id { get; set; }
             public int id { get; set; }
 
 
-            [Property(name = "ColumnName", value = "name")]
+            [Property(name = "ColumnName", value = "userName")]
             [Property(name = "TypeName", value = "varchar(1000)")]
             [Property(name = "TypeName", value = "varchar(1000)")]
             [Label("Required")]
             [Label("Required")]
             public string name { get; set; }
             public string name { get; set; }
+
+            [Property(name = "ColumnName", value = "userBirth")]
             public DateTime? birth { get; set; }
             public DateTime? birth { get; set; }
 
 
+            [Property(name = "ColumnName", value = "userFatherId")]
             public int? fatherId { get; set; }
             public int? fatherId { get; set; }
+            [Property(name = "ColumnName", value = "userMotherId")]
             public int? motherId { get; set; }
             public int? motherId { get; set; }
 
 
             [Label("NotMapped")]
             [Label("NotMapped")]
@@ -128,7 +135,7 @@ namespace Vitorm.MsTest.CommonTest
                         bool isKey = labels.Any(m => m.label == "Key");
                         bool isKey = labels.Any(m => m.label == "Key");
 
 
                         // #2 column name and type
                         // #2 column name and type
-                        var name = properties.FirstOrDefault(attr => attr.name == "ColumnName")?.value ?? propertyInfo.Name;
+                        var columnName = properties.FirstOrDefault(attr => attr.name == "ColumnName")?.value ?? propertyInfo.Name;
                         var databaseType = properties.FirstOrDefault(attr => attr.name == "TypeName")?.value;
                         var databaseType = properties.FirstOrDefault(attr => attr.name == "TypeName")?.value;
                         int? columnOrder = int.TryParse(properties.FirstOrDefault(attr => attr.name == "ColumnOrder")?.value, out var order) ? order : null;
                         int? columnOrder = int.TryParse(properties.FirstOrDefault(attr => attr.name == "ColumnOrder")?.value, out var order) ? order : null;
 
 
@@ -148,7 +155,7 @@ namespace Vitorm.MsTest.CommonTest
                             }
                             }
                         }
                         }
 
 
-                        return new ColumnDescriptor(propertyInfo, name: name, isKey: isKey, isIdentity: isIdentity, databaseType: databaseType, isNullable: isNullable, columnOrder: columnOrder);
+                        return new ColumnDescriptor(propertyInfo, columnName: columnName, isKey: isKey, isIdentity: isIdentity, databaseType: databaseType, isNullable: isNullable, columnOrder: columnOrder);
                     }).Where(column => column != null).ToArray();
                     }).Where(column => column != null).ToArray();
 
 
                 return new EntityDescriptor(entityType, allColumns, tableName, schema);
                 return new EntityDescriptor(entityType, allColumns, tableName, schema);

+ 2 - 2
test/Vitorm.Sqlite.MsTest/CommonTest/Query_Group_Test.cs

@@ -15,7 +15,7 @@ namespace Vitorm.MsTest.CommonTest
             using var dbContext = DataSource.CreateDbContext();
             using var dbContext = DataSource.CreateDbContext();
             var userQuery = dbContext.Query<User>();
             var userQuery = dbContext.Query<User>();
 
 
-            // Linq Expresssion
+            // Linq Expression
             {
             {
                 var query =
                 var query =
                         from user in userQuery
                         from user in userQuery
@@ -58,7 +58,7 @@ namespace Vitorm.MsTest.CommonTest
             using var dbContext = DataSource.CreateDbContext();
             using var dbContext = DataSource.CreateDbContext();
             var userQuery = dbContext.Query<User>();
             var userQuery = dbContext.Query<User>();
 
 
-            // Linq Expresssion
+            // Linq Expression
             {
             {
                 var query =
                 var query =
                         from user in userQuery.Where(u => u.id > 1)
                         from user in userQuery.Where(u => u.id > 1)

+ 2 - 2
test/Vitorm.Sqlite.MsTest/CommonTest/Query_InnerJoin_ByJoin_Test.cs

@@ -15,7 +15,7 @@ namespace Vitorm.MsTest.CommonTest
             using var dbContext = DataSource.CreateDbContext();
             using var dbContext = DataSource.CreateDbContext();
             var userQuery = dbContext.Query<User>();
             var userQuery = dbContext.Query<User>();
 
 
-            // Linq Expresssion
+            // Linq Expression
             {
             {
                 var query =
                 var query =
                     from user in userQuery
                     from user in userQuery
@@ -58,7 +58,7 @@ namespace Vitorm.MsTest.CommonTest
             using var dbContext = DataSource.CreateDbContext();
             using var dbContext = DataSource.CreateDbContext();
             var userQuery = dbContext.Query<User>();
             var userQuery = dbContext.Query<User>();
 
 
-            // Linq Expresssion
+            // Linq Expression
             {
             {
                 var query =
                 var query =
                     from user in userQuery
                     from user in userQuery

+ 2 - 2
test/Vitorm.Sqlite.MsTest/CommonTest/Query_InnerJoin_BySelectMany_Test.cs

@@ -15,7 +15,7 @@ namespace Vitorm.MsTest.CommonTest
             using var dbContext = DataSource.CreateDbContext();
             using var dbContext = DataSource.CreateDbContext();
             var userQuery = dbContext.Query<User>();
             var userQuery = dbContext.Query<User>();
 
 
-            // Linq Expresssion
+            // Linq Expression
             {
             {
                 var query =
                 var query =
                     from user in userQuery
                     from user in userQuery
@@ -57,7 +57,7 @@ namespace Vitorm.MsTest.CommonTest
             using var dbContext = DataSource.CreateDbContext();
             using var dbContext = DataSource.CreateDbContext();
             var userQuery = dbContext.Query<User>();
             var userQuery = dbContext.Query<User>();
 
 
-            // Linq Expresssion
+            // Linq Expression
             {
             {
                 var query =
                 var query =
                     from user in userQuery
                     from user in userQuery

+ 2 - 2
test/Vitorm.Sqlite.MsTest/CommonTest/Query_LeftJoin_ByGroupJoin_Test.cs

@@ -14,7 +14,7 @@ namespace Vitorm.MsTest.CommonTest
             using var dbContext = DataSource.CreateDbContext();
             using var dbContext = DataSource.CreateDbContext();
             var userQuery = dbContext.Query<User>();
             var userQuery = dbContext.Query<User>();
 
 
-            // Linq Expresssion
+            // Linq Expression
             {
             {
                 var query =
                 var query =
                     from user in userQuery
                     from user in userQuery
@@ -69,7 +69,7 @@ namespace Vitorm.MsTest.CommonTest
             using var dbContext = DataSource.CreateDbContext();
             using var dbContext = DataSource.CreateDbContext();
             var userQuery = dbContext.Query<User>();
             var userQuery = dbContext.Query<User>();
 
 
-            // Linq Expresssion
+            // Linq Expression
             {
             {
                 var query =
                 var query =
                     from user in userQuery
                     from user in userQuery

+ 6 - 3
test/Vitorm.Sqlite.MsTest/CommonTest/Query_LeftJoin_BySelectMany_Test.cs

@@ -17,7 +17,7 @@ namespace Vitorm.MsTest.CommonTest
             using var dbContext = DataSource.CreateDbContext();
             using var dbContext = DataSource.CreateDbContext();
             var userQuery = dbContext.Query<User>();
             var userQuery = dbContext.Query<User>();
 
 
-            // Linq Expresssion
+            // Linq Expression
             {
             {
                 var query =
                 var query =
                         from user in userQuery
                         from user in userQuery
@@ -66,19 +66,22 @@ namespace Vitorm.MsTest.CommonTest
             using var dbContext = DataSource.CreateDbContext();
             using var dbContext = DataSource.CreateDbContext();
             var userQuery = dbContext.Query<User>();
             var userQuery = dbContext.Query<User>();
 
 
-            // Linq Expresssion
+            // Linq Expression
             {
             {
                 var query =
                 var query =
                     from user in userQuery
                     from user in userQuery
                     from father in userQuery.Where(father => user.fatherId == father.id).DefaultIfEmpty()
                     from father in userQuery.Where(father => user.fatherId == father.id).DefaultIfEmpty()
                     from mother in userQuery.Where(mother => user.motherId == mother.id).DefaultIfEmpty()
                     from mother in userQuery.Where(mother => user.motherId == mother.id).DefaultIfEmpty()
-                    where user.id > 2
+                    from userClass in dbContext.Query<UserClass>().Where(userClass => user.classId == userClass.id).DefaultIfEmpty()
+                    where user.id > 1 && userClass.id == 1
                     orderby user.id
                     orderby user.id
                     select new
                     select new
                     {
                     {
                         user,
                         user,
                         father,
                         father,
                         mother,
                         mother,
+                        userClass,
+                        userClass.name,
                         testId = user.id + 100,
                         testId = user.id + 100,
                         hasFather = father.name != null ? true : false
                         hasFather = father.name != null ? true : false
                     };
                     };

+ 44 - 6
test/Vitorm.Sqlite.MsTest/DataSource.cs

@@ -1,4 +1,5 @@
 using Vit.Extensions;
 using Vit.Extensions;
+
 using Vitorm.Sql;
 using Vitorm.Sql;
 
 
 namespace Vitorm.MsTest
 namespace Vitorm.MsTest
@@ -7,12 +8,18 @@ namespace Vitorm.MsTest
     public class User
     public class User
     {
     {
         [System.ComponentModel.DataAnnotations.Key]
         [System.ComponentModel.DataAnnotations.Key]
+        [System.ComponentModel.DataAnnotations.Schema.Column("userId")]
         public int id { get; set; }
         public int id { get; set; }
+        [System.ComponentModel.DataAnnotations.Schema.Column("userName")]
         public string name { get; set; }
         public string name { get; set; }
+        [System.ComponentModel.DataAnnotations.Schema.Column("userBirth")]
         public DateTime? birth { get; set; }
         public DateTime? birth { get; set; }
-
+        [System.ComponentModel.DataAnnotations.Schema.Column("userFatherId")]
         public int? fatherId { get; set; }
         public int? fatherId { get; set; }
+        [System.ComponentModel.DataAnnotations.Schema.Column("userMotherId")]
         public int? motherId { get; set; }
         public int? motherId { get; set; }
+        [System.ComponentModel.DataAnnotations.Schema.Column("userClassId")]
+        public int? classId { get; set; }
 
 
         [System.ComponentModel.DataAnnotations.Schema.NotMapped]
         [System.ComponentModel.DataAnnotations.Schema.NotMapped]
         public string test { get; set; }
         public string test { get; set; }
@@ -26,6 +33,21 @@ namespace Vitorm.MsTest
         }
         }
     }
     }
 
 
+    [System.ComponentModel.DataAnnotations.Schema.Table("UserClass")]
+    public class UserClass
+    {
+        [System.ComponentModel.DataAnnotations.Key]
+        [System.ComponentModel.DataAnnotations.Schema.Column("classId")]
+        public int id { get; set; }
+        [System.ComponentModel.DataAnnotations.Schema.Column("className")]
+        public string name { get; set; }
+
+        public static List<UserClass> NewClasses(int startId, int count = 1)
+        {
+            return Enumerable.Range(startId, count).Select(id => new UserClass { id = id, name = "class" + id }).ToList();
+        }
+    }
+
 
 
     public class DataSource
     public class DataSource
     {
     {
@@ -47,10 +69,12 @@ namespace Vitorm.MsTest
 
 
             dbContext.BeginTransaction();
             dbContext.BeginTransaction();
 
 
-            var dbSet = dbContext.DbSet<User>();
-            dbSet.Create();
 
 
-            var users = new List<User> {
+            #region #1 init User
+            {
+                dbContext.Create<User>();
+
+                var users = new List<User> {
                     new User { id=1, name="u146", fatherId=4, motherId=6 },
                     new User { id=1, name="u146", fatherId=4, motherId=6 },
                     new User { id=2, name="u246", fatherId=4, motherId=6 },
                     new User { id=2, name="u246", fatherId=4, motherId=6 },
                     new User { id=3, name="u356", fatherId=5, motherId=6 },
                     new User { id=3, name="u356", fatherId=5, motherId=6 },
@@ -58,9 +82,23 @@ namespace Vitorm.MsTest
                     new User { id=5, name="u500" },
                     new User { id=5, name="u500" },
                     new User { id=6, name="u600" },
                     new User { id=6, name="u600" },
                 };
                 };
-            users.ForEach(user => { user.birth = DateTime.Parse("2021-01-01 00:00:00").AddHours(user.id); });
+                users.ForEach(user =>
+                {
+                    user.birth = DateTime.Parse("2021-01-01 00:00:00").AddHours(user.id);
+                    user.classId = user.id % 2 + 1;
+                });
+
+                dbContext.AddRange(users);
+            }
+            #endregion
+
+            #region #2 init Class
+            {
+                dbContext.Create<UserClass>();
+                dbContext.AddRange(UserClass.NewClasses(1, 6));
+            }
+            #endregion
 
 
-            dbContext.AddRange(users);
 
 
             return dbContext;
             return dbContext;
         }
         }