예제 #1
0
        public static IDbValueReader GetDbValueReader(Type type)
        {
            var handler = GetValueHandlerCache.GetOrAdd(type, valueType =>
            {
                valueType = valueType.GetUnderlyingType();
                if (valueType.IsEnum)
                {
                    return(new DbValueReader((IDataReader reader, int ordinal) =>
                    {
                        object value = reader.GetEnum(ordinal, valueType);
                        return value;
                    }));
                }

                Infrastructure.MappingType mappingType = MappingTypeSystem.GetMappingType(valueType);

                return(new DbValueReader((IDataReader reader, int ordinal) =>
                {
                    object value = DataReaderExtension.GetValue(reader, ordinal);
                    if (value == null)
                    {
                        return null;
                    }

                    if (value.GetType() == mappingType.Type)
                    {
                        return value;
                    }

                    return mappingType.DbValueConverter.Convert(value);
                }));
            });

            return(handler);
        }
예제 #2
0
파일: Program.cs 프로젝트: jeason0813/Chloe
        public static void Main(string[] args)
        {
            string s  = Guid.NewGuid().ToString("N");
            string s1 = Guid.NewGuid().ToString();

            Int16  shortId = 2;
            int    id      = 2;
            long   longId  = 2;
            Gender gender  = Gender.Man;

            User u = new User();
            //u.Age = 1; ;
            int?i = null;
            Expression <Func <int, object> > e = a => (Gender)longId;

            //var b = ExpressionEvaluator.Evaluate(e.Body);

            MappingTypeSystem.Configure(new String_MappingType());
            IDbCommandInterceptor interceptor = new DbCommandInterceptor();

            DbInterception.Add(interceptor);

            //FeatureTest_SQLite.Test();
            //FeatureTest.Test();
            //MySqlDemo.Run();
            //OracleDemo.Run();
            PostgreSQLTest.Test();
        }
예제 #3
0
        public static DbParam[] BuildParams(DbContext dbContext, object parameter)
        {
            if (parameter == null)
            {
                return(new DbParam[0]);
            }

            if (parameter is IEnumerable <DbParam> )
            {
                return(((IEnumerable <DbParam>)parameter).ToArray());
            }

            List <DbParam> parameters    = new List <DbParam>();
            Type           parameterType = parameter.GetType();
            var            props         = parameterType.GetProperties();

            foreach (var prop in props)
            {
                if (prop.GetGetMethod() == null || !MappingTypeSystem.IsMappingType(prop.GetMemberType()))
                {
                    continue;
                }

                object value = ReflectionExtension.GetMemberValue(prop, parameter);

                string paramName = dbContext.DatabaseProvider.CreateParameterName(prop.Name);

                DbParam p = new DbParam(paramName, value, prop.PropertyType);
                parameters.Add(p);
            }

            return(parameters.ToArray());
        }
예제 #4
0
        protected override IMappingObjectExpression VisitMemberInit(MemberInitExpression exp)
        {
            IMappingObjectExpression result = this.Visit(exp.NewExpression);

            foreach (MemberBinding binding in exp.Bindings)
            {
                if (binding.BindingType != MemberBindingType.Assignment)
                {
                    throw new NotSupportedException();
                }

                MemberAssignment memberAssignment = (MemberAssignment)binding;
                MemberInfo       member           = memberAssignment.Member;
                Type             memberType       = member.GetMemberType();

                //是数据库映射类型
                if (MappingTypeSystem.IsMappingType(memberType))
                {
                    DbExpression dbExpression = this.ResolveExpression(memberAssignment.Expression);
                    result.AddMappingMemberExpression(member, dbExpression);
                }
                else
                {
                    //对于非数据库映射类型,只支持 NewExpression 和 MemberInitExpression
                    IMappingObjectExpression subResult = this.Visit(memberAssignment.Expression);
                    result.AddComplexMemberExpression(member, subResult);
                }
            }

            return(result);
        }
예제 #5
0
 static void EnsureIsMappingType(Type type, MethodCallExpression exp)
 {
     if (!MappingTypeSystem.IsMappingType(type))
     {
         throw new NotSupportedException(string.Format("The generic parameter type of method {0} must be mapping type.", exp.Method.Name));
     }
 }
예제 #6
0
        void Init()
        {
            Type t       = this.Type;
            var  members = t.GetMembers(BindingFlags.Public | BindingFlags.Instance);

            Dictionary <MemberInfo, IMRM> mappingMemberMappers = new Dictionary <MemberInfo, IMRM>();
            Dictionary <MemberInfo, Action <object, object> > complexMemberSetters = new Dictionary <MemberInfo, Action <object, object> >();

            foreach (var member in members)
            {
                Type         memberType = null;
                PropertyInfo prop       = null;
                FieldInfo    field      = null;

                if ((prop = member as PropertyInfo) != null)
                {
                    if (prop.GetSetMethod() == null)
                    {
                        continue;//对于没有公共的 setter 直接跳过
                    }
                    memberType = prop.PropertyType;
                }
                else if ((field = member as FieldInfo) != null)
                {
                    memberType = field.FieldType;
                }
                else
                {
                    continue;//只支持公共属性和字段
                }
                MappingTypeInfo mappingTypeInfo;
                if (MappingTypeSystem.IsMappingType(memberType, out mappingTypeInfo))
                {
                    IMRM mrm = MRMHelper.CreateMRM(member, mappingTypeInfo);
                    mappingMemberMappers.Add(member, mrm);
                }
                else
                {
                    if (prop != null)
                    {
                        Action <object, object> valueSetter = DelegateGenerator.CreateValueSetter(prop);
                        complexMemberSetters.Add(member, valueSetter);
                    }
                    else if (field != null)
                    {
                        Action <object, object> valueSetter = DelegateGenerator.CreateValueSetter(field);
                        complexMemberSetters.Add(member, valueSetter);
                    }
                    else
                    {
                        continue;
                    }

                    continue;
                }
            }

            this._mappingMemberMappers = Utils.Clone(mappingMemberMappers);
            this._complexMemberSetters = Utils.Clone(complexMemberSetters);
        }
예제 #7
0
        void ConfigureNavigationProperty()
        {
            PropertyInfo[] properties = this.EntityType.Type.GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(a => a.GetSetMethod() != null && a.GetGetMethod() != null).ToArray();

            foreach (PropertyInfo property in properties)
            {
                if (MappingTypeSystem.IsMappingType(property.PropertyType))
                {
                    continue;
                }

                NavigationAttribute navigationAttribute = property.GetCustomAttribute <NavigationAttribute>();

                if (navigationAttribute == null)
                {
                    continue;
                }

                if (this.IsSupportedCollectionType(property.PropertyType))
                {
                    this.EntityType.CollectionProperties.Add(new CollectionProperty(property));
                    continue;
                }

                ComplexProperty complexProperty = new ComplexProperty(property);
                complexProperty.ForeignKey = navigationAttribute.ForeignKey;
                this.EntityType.ComplexProperties.Add(complexProperty);
            }
        }
예제 #8
0
        void Init()
        {
            Type t       = this.Type;
            var  members = t.GetMembers(BindingFlags.Public | BindingFlags.Instance);

            Dictionary <MemberInfo, IMRM> mappingMemberMappers = new Dictionary <MemberInfo, IMRM>();
            Dictionary <MemberInfo, Action <object, object> > complexMemberSetters = new Dictionary <MemberInfo, Action <object, object> >();

            foreach (var member in members)
            {
                if (!member.HasPublicSetter())
                {
                    continue;
                }

                //只支持公共属性和字段
                Type memberType = member.GetMemberType();

                MappingTypeInfo mappingTypeInfo;
                if (MappingTypeSystem.IsMappingType(memberType, out mappingTypeInfo))
                {
                    IMRM mrm = MRMHelper.CreateMRM(member, mappingTypeInfo);
                    mappingMemberMappers.Add(member, mrm);
                }
                else
                {
                    Action <object, object> valueSetter = DelegateGenerator.CreateValueSetter(member);
                    complexMemberSetters.Add(member, valueSetter);
                }
            }

            this._mappingMemberMappers = PublicHelper.Clone(mappingMemberMappers);
            this._complexMemberSetters = PublicHelper.Clone(complexMemberSetters);
        }
예제 #9
0
        void Init()
        {
            Type t       = this.Type;
            var  members = t.GetMembers(BindingFlags.Public | BindingFlags.Instance);
            Dictionary <MemberInfo, MRMTuple> mappingMemberMappers           = new Dictionary <MemberInfo, MRMTuple>();
            Dictionary <MemberInfo, Lazy <MemberValueSetter> > memberSetters = new Dictionary <MemberInfo, Lazy <MemberValueSetter> >();

            foreach (var member in members)
            {
                if (!member.HasPublicSetter())
                {
                    continue;
                }

                //只支持公共属性和字段
                Type memberType = member.GetMemberType();

                memberSetters.Add(member, new Lazy <MemberValueSetter>(() =>
                {
                    MemberValueSetter valueSetter = MemberValueSetterContainer.GetMemberValueSetter(member);
                    return(valueSetter);
                }, LazyThreadSafetyMode.ExecutionAndPublication));

                Infrastructure.MappingType mappingType;
                if (MappingTypeSystem.IsMappingType(memberType, out mappingType))
                {
                    MRMTuple mrmTuple = MRMHelper.CreateMRMTuple(member, mappingType);
                    mappingMemberMappers.Add(member, mrmTuple);
                }
            }

            this._mappingMemberMappers = PublicHelper.Clone(mappingMemberMappers);
            this._memberSetters        = PublicHelper.Clone(memberSetters);
        }
예제 #10
0
        /*sql script:
         * CREATE TABLE [dbo].[ExtensionMappingType](
         *      [Id] [int] IDENTITY(1,1) NOT NULL,
         *      [Name] [nvarchar](100) NULL,
         *      [F_Char] [nvarchar](1) NULL,
         *      [F_Time] [time](7) NULL,
         * CONSTRAINT [PK_ExtensionMappingType] PRIMARY KEY CLUSTERED
         * (
         *      [Id] ASC
         * )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
         * ) ON [PRIMARY]
         */

        public static void RunDemo()
        {
            //step 1:
            /* 原生 Chloe 不支持 char 和 TimeSpan 类型映射,需要我们自己注册,注册映射类必须在程序启动时进行 */
            MappingTypeSystem.Configure(typeof(char), DbType.StringFixedLength);
            MappingTypeSystem.Configure(typeof(TimeSpan), DbType.Time);

            //step 2:
            /* 因为我们新增了 MappingType,所以需要对原生的 SqlConnection、SqlServerCommand、SqlServerDataReader、SqlServerParameter 包装处理,所以,我们需要自个儿实现 IDbConnectionFactory 工厂  */
            SqlServerDbConnectionFactory sqlServerDbConnectionFactory = new SqlServerDbConnectionFactory(DbHelper.ConnectionString);
            MsSqlContext context = new MsSqlContext(sqlServerDbConnectionFactory);

            /* 经过上述封装,我们就可以支持 char 和 TimeSpan 类型映射了 */

            ExtensionMappingType entity = new ExtensionMappingType();

            entity.Name   = "test";
            entity.F_Char = 'A';
            entity.F_Time = TimeSpan.FromHours(12);
            context.Insert(entity);
            Console.WriteLine(entity.Id);

            TimeSpan             ts    = TimeSpan.FromHours(12);
            ExtensionMappingType model = context.Query <ExtensionMappingType>().Where(a => a.F_Time == ts && a.Id == entity.Id).First();

            Console.WriteLine(model.Id == entity.Id);


            Console.WriteLine("Yeah!!");
            Console.ReadKey();
        }
예제 #11
0
        IObjectActivator CreateObjectActivator(IDataReader dataReader)
        {
            Type type = typeof(T);

            if (type != PublicConstants.TypeOfObject && MappingTypeSystem.IsMappingType(type))
            {
                PrimitiveObjectActivatorCreator activatorCreator = new PrimitiveObjectActivatorCreator(type, 0);
                return(activatorCreator.CreateObjectActivator());
            }

            return(GetObjectActivator(type, dataReader));
        }
예제 #12
0
        IMappingObjectExpression VisistMapTypeSelector(Expression exp)
        {
            if (!MappingTypeSystem.IsMappingType(exp.Type))
            {
                throw new NotSupportedException(exp.ToString());
            }

            DbExpression           dbExp = this.ResolveExpression(exp);
            MappingFieldExpression ret   = new MappingFieldExpression(exp.Type, dbExp);

            return(ret);
        }
예제 #13
0
        IObjectModel VisistMapTypeSelector(Expression exp)
        {
            if (!MappingTypeSystem.IsMappingType(exp.Type))
            {
                throw new NotSupportedException(exp.ToString());
            }

            DbExpression         dbExp = this.ResolveExpression(exp);
            PrimitiveObjectModel ret   = new PrimitiveObjectModel(exp.Type, dbExp);

            return(ret);
        }
예제 #14
0
        /// <summary>
        /// a => a.Id   a => a.Name   a => a.User
        /// </summary>
        /// <param name="exp"></param>
        /// <returns></returns>
        protected override IMappingObjectExpression VisitMemberAccess(MemberExpression exp)
        {
            //create MappingFieldExpression object if exp is map type
            if (MappingTypeSystem.IsMappingType(exp.Type))
            {
                DbExpression           dbExp = this.ResolveExpression(exp);
                MappingFieldExpression ret   = new MappingFieldExpression(exp.Type, dbExp);
                return(ret);
            }

            //如 a.Order a.User 等形式
            return(this.ResolveComplexMember(exp));
        }
예제 #15
0
            void Prepare()
            {
                Type type = typeof(T);

                if (type != UtilConstants.TypeOfObject && MappingTypeSystem.IsMappingType(type))
                {
                    PrimitiveObjectActivatorCreator activatorCreator = new PrimitiveObjectActivatorCreator(type, 0);
                    this._objectActivator = activatorCreator.CreateObjectActivator();
                    this._reader          = this.ExecuteReader();
                    return;
                }

                this._reader          = this.ExecuteReader();
                this._objectActivator = GetObjectActivator(type, this._reader);
            }
예제 #16
0
        protected override DbExpression VisitParameter(ParameterExpression exp)
        {
            //TODO 只支持 MappingFieldExpression 类型,即类似 q.Select(a=> a.Id).Where(a=> a > 0) 这种情况,也就是 ParameterExpression.Type 为基本映射类型。

            if (MappingTypeSystem.IsMappingType(exp.Type))
            {
                IMappingObjectExpression moe = this.FindMoe(exp);
                MappingFieldExpression   mfe = (MappingFieldExpression)moe;
                return(mfe.Expression);
            }
            else
            {
                throw new NotSupportedException(exp.ToString());
            }
        }
예제 #17
0
            void Prepare()
            {
                Type type = typeof(T);

                if (MappingTypeSystem.IsMappingType(type))
                {
                    MappingField mf = new MappingField(type, 0);
                    this._objectActivator = mf.CreateObjectActivator();
                    this._reader          = this.ExecuteReader();
                    return;
                }

                this._reader          = this.ExecuteReader();
                this._objectActivator = GetObjectActivator(type, this._reader);
            }
예제 #18
0
        protected override DbExpression VisitParameter(ParameterExpression exp)
        {
            //只支持 MappingFieldExpression 类型,即类似 q.Select(a=> a.Id).Where(a=> a > 0) 这种情况,也就是 ParameterExpression.Type 为基本映射类型。

            if (MappingTypeSystem.IsMappingType(exp.Type))
            {
                IObjectModel         model       = this.FindModel(exp);
                PrimitiveObjectModel resultModel = (PrimitiveObjectModel)model;
                return(resultModel.Expression);
            }
            else
            {
                throw new NotSupportedException(exp.ToString());
            }
        }
예제 #19
0
        public EntityType(Type type)
        {
            this.Type      = type;
            this.TableName = type.Name;

            PropertyInfo[] properties = this.Type.GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(a => a.GetSetMethod() != null && a.GetGetMethod() != null).ToArray();

            foreach (PropertyInfo property in properties)
            {
                if (!MappingTypeSystem.IsMappingType(property.PropertyType))
                {
                    continue;
                }

                this.Properties.Add(new EntityProperty(property));
            }
        }
예제 #20
0
            async Task Prepare(bool @async)
            {
                Type type = typeof(T);

                if (type != PublicConstants.TypeOfObject && MappingTypeSystem.IsMappingType(type))
                {
                    PrimitiveObjectActivatorCreator activatorCreator = new PrimitiveObjectActivatorCreator(type, 0);
                    this._objectActivator = activatorCreator.CreateObjectActivator();
                    this._reader          = await this.ExecuteReader(@async);

                    return;
                }

                this._reader = await this.ExecuteReader(@async);

                this._objectActivator = GetObjectActivator(type, this._reader);
            }
예제 #21
0
        public static Func <IDataReader, ReaderOrdinalEnumerator, ObjectActivatorEnumerator, object> CreateObjectGenerator(ConstructorInfo constructor)
        {
            Utils.CheckNull(constructor);

            Func <IDataReader, ReaderOrdinalEnumerator, ObjectActivatorEnumerator, object> ret = null;

            var pExp_reader = Expression.Parameter(typeof(IDataReader), "reader");
            var pExp_readerOrdinalEnumerator   = Expression.Parameter(typeof(ReaderOrdinalEnumerator), "readerOrdinalEnumerator");
            var pExp_objectActivatorEnumerator = Expression.Parameter(typeof(ObjectActivatorEnumerator), "objectActivatorEnumerator");

            ParameterInfo[]   parameters = constructor.GetParameters();
            List <Expression> arguments  = new List <Expression>(parameters.Length);

            foreach (ParameterInfo parameter in parameters)
            {
                if (MappingTypeSystem.IsMappingType(parameter.ParameterType))
                {
                    var readerMethod = DataReaderConstant.GetReaderMethod(parameter.ParameterType);
                    //int ordinal = readerOrdinalEnumerator.Next();
                    var readerOrdinal = Expression.Call(pExp_readerOrdinalEnumerator, ReaderOrdinalEnumerator.MethodOfNext);
                    //DataReaderExtensions.GetValue(reader,readerOrdinal)
                    var getValue = Expression.Call(readerMethod, pExp_reader, readerOrdinal);
                    arguments.Add(getValue);
                }
                else
                {
                    //IObjectActivator oa = objectActivatorEnumerator.Next();
                    var oa = Expression.Call(pExp_objectActivatorEnumerator, ObjectActivatorEnumerator.MethodOfNext);
                    //object obj = oa.CreateInstance(IDataReader reader);
                    var entity = Expression.Call(oa, typeof(IObjectActivator).GetMethod("CreateInstance"), pExp_reader);
                    //(T)entity;
                    var val = Expression.Convert(entity, parameter.ParameterType);
                    arguments.Add(val);
                }
            }

            var body = Expression.New(constructor, arguments);

            ret = Expression.Lambda <Func <IDataReader, ReaderOrdinalEnumerator, ObjectActivatorEnumerator, object> >(body, pExp_reader, pExp_readerOrdinalEnumerator, pExp_objectActivatorEnumerator).Compile();

            return(ret);
        }
예제 #22
0
        public EntityType(Type type)
        {
            this.Type      = type;
            this.TableName = type.Name;

            PropertyInfo[] properties = this.Type.GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(a => a.GetSetMethod() != null && a.GetGetMethod() != null).ToArray();

            foreach (PropertyInfo property in properties)
            {
                MappingType mappingType;
                if (!MappingTypeSystem.IsMappingType(property.PropertyType, out mappingType))
                {
                    continue;
                }

                PrimitiveProperty primitiveProperty = new PrimitiveProperty(property);
                primitiveProperty.DbType     = mappingType.DbType;
                primitiveProperty.IsNullable = property.PropertyType.CanNull();

                if (string.Equals(property.Name, "id", StringComparison.OrdinalIgnoreCase))
                {
                    /* 默认为主键 */
                    primitiveProperty.IsPrimaryKey = true;

                    if (Utils.IsAutoIncrementType(property.PropertyType))
                    {
                        primitiveProperty.IsAutoIncrement = true;
                    }

                    if (property.PropertyType == typeof(string))
                    {
                        //如果主键是 string 类型,默认为 AnsiString
                        primitiveProperty.DbType = System.Data.DbType.AnsiString;
                    }
                }

                this.PrimitiveProperties.Add(primitiveProperty);
            }
        }
예제 #23
0
        List <MappingMemberDescriptor> ExtractMappingMemberDescriptors()
        {
            var members = this.EntityType.GetMembers(BindingFlags.Public | BindingFlags.Instance);

            List <MappingMemberDescriptor> mappingMemberDescriptors = new List <MappingMemberDescriptor>();

            foreach (var member in members)
            {
                if (ShouldMap(member) == false)
                {
                    continue;
                }

                if (MappingTypeSystem.IsMappingType(member.GetMemberType()))
                {
                    MappingMemberDescriptor memberDescriptor = new MappingMemberDescriptor(member, this);
                    mappingMemberDescriptors.Add(memberDescriptor);
                }
            }

            return(mappingMemberDescriptors);
        }
예제 #24
0
        protected override IMappingObjectExpression VisitNew(NewExpression exp)
        {
            IMappingObjectExpression result = new MappingObjectExpression(exp.Constructor);

            ParameterInfo[] parames = exp.Constructor.GetParameters();
            for (int i = 0; i < parames.Length; i++)
            {
                ParameterInfo pi     = parames[i];
                Expression    argExp = exp.Arguments[i];
                if (MappingTypeSystem.IsMappingType(pi.ParameterType))
                {
                    DbExpression dbExpression = this.ResolveExpression(argExp);
                    result.AddMappingConstructorParameter(pi, dbExpression);
                }
                else
                {
                    IMappingObjectExpression subResult = this.Visit(argExp);
                    result.AddComplexConstructorParameter(pi, subResult);
                }
            }

            return(result);
        }
예제 #25
0
        protected virtual IDbCommand PrepareCommand(string cmdText, DbParam[] parameters, CommandType cmdType, out List <OutputParameter> outputParameters)
        {
            outputParameters = null;

            IDbCommand cmd = this.DbConnection.CreateCommand();

            cmd.CommandText    = cmdText;
            cmd.CommandType    = cmdType;
            cmd.CommandTimeout = this.CommandTimeout;
            if (this.IsInTransaction)
            {
                cmd.Transaction = this.DbTransaction;
            }

            if (parameters != null)
            {
                for (int i = 0; i < parameters.Length; i++)
                {
                    DbParam param = parameters[i];
                    if (param == null)
                    {
                        continue;
                    }

                    if (param.ExplicitParameter != null)/* 如果存在创建好了的 IDbDataParameter,则直接用它。同时也忽视了 DbParam 的其他属性 */
                    {
                        cmd.Parameters.Add(param.ExplicitParameter);
                        continue;
                    }

                    Type parameterType;
                    if (param.Value == null || param.Value == DBNull.Value)
                    {
                        parameterType = param.Type ?? typeof(object);
                    }
                    else
                    {
                        parameterType = param.Value.GetType();
                        if (parameterType.IsEnum)
                        {
                            parameterType = Enum.GetUnderlyingType(parameterType);
                        }
                    }

                    IDbDataParameter           parameter   = cmd.CreateParameter();
                    Infrastructure.MappingType mappingType = MappingTypeSystem.GetMappingType(parameterType);
                    mappingType.DbParameterAssembler.SetupParameter(parameter, param);

                    cmd.Parameters.Add(parameter);

                    OutputParameter outputParameter = null;
                    if (param.Direction == ParamDirection.Output || param.Direction == ParamDirection.InputOutput)
                    {
                        outputParameter = new OutputParameter(param, parameter);
                        if (outputParameters == null)
                        {
                            outputParameters = new List <OutputParameter>();
                        }
                        outputParameters.Add(outputParameter);
                    }
                }
            }

            return(cmd);
        }
예제 #26
0
        DbExpression Process_MemberAccess_Which_Link_First_Or_FirstOrDefault(MemberExpression exp)
        {
            /*
             * 判断是不是 First().xx,FirstOrDefault().xx 之类的
             * First().Name: 泛型参数如果不是复杂类型,则转成 Select(a=> a.Name).First()
             * First().xx.Name:  如果 xx 是复杂类型,则转成 Select(a=> a.xx.Name).First()
             * First().xx.Name.Length:  如果 xx 是复杂类型,则转成 Select(a=> a.xx.Name).First().Length
             */

            // 分割
            MethodCallExpression     methodCall = null;
            Stack <MemberExpression> memberExps = new Stack <MemberExpression>();

            Expression e = exp;

            while (e.NodeType == ExpressionType.MemberAccess)
            {
                MemberExpression memberExpression = (MemberExpression)e;
                memberExps.Push(memberExpression);
                e = memberExpression.Expression;
            }

            methodCall = (MethodCallExpression)e;
            methodCall = OptimizeCondition(methodCall);

            if (!MappingTypeSystem.IsMappingType(methodCall.Type))
            {
                /*
                 * query.First().xx.Name.Length --> query.Select(a=> a.xx.Name).First().Length
                 */

                ParameterExpression parameter    = Expression.Parameter(methodCall.Type, "a");
                Expression          selectorBody = parameter;
                while (memberExps.Count != 0)
                {
                    MemberExpression memberExpression = memberExps.Pop();
                    selectorBody = Expression.MakeMemberAccess(parameter, memberExpression.Member);

                    if (MappingTypeSystem.IsMappingType(selectorBody.Type))
                    {
                        break;
                    }
                }

                Type             delegateType = typeof(Func <,>).MakeGenericType(parameter.Type, selectorBody.Type);
                LambdaExpression selector     = Expression.Lambda(delegateType, selectorBody, parameter);
                var selectMethod = methodCall.Object.Type.GetMethod("Select");
                selectMethod = selectMethod.MakeGenericMethod(selectorBody.Type);
                var selectMethodCall = Expression.Call(methodCall.Object, selectMethod, Expression.Quote(selector)); /* query.Select(a=> a.xx.Name) */

                var sameNameMethod     = selectMethodCall.Type.GetMethod(methodCall.Method.Name, Type.EmptyTypes);
                var sameNameMethodCall = Expression.Call(selectMethodCall, sameNameMethod); /* query.Select(a=> a.xx.Name).First() */

                methodCall = sameNameMethodCall;
            }

            DbExpression dbExpression = this.Visit(methodCall);

            while (memberExps.Count != 0)
            {
                MemberExpression memberExpression = memberExps.Pop();
                dbExpression = DbExpression.MemberAccess(memberExpression.Member, dbExpression);
            }

            return(dbExpression);
        }
예제 #27
0
        static Expression <Func <TEntity, bool> > BuildPredicate <TEntity>(object key)
        {
            /*
             * key:
             * 如果实体是单一主键,可以传入的 key 与主键属性类型相同的值,亦可以传一个包含了与实体主键类型相同的属性的对象,如:new { Id = 1 }
             * 如果实体是多主键,则传入的 key 须是包含了与实体主键类型相同的属性的对象,如:new { Key1 = "1", Key2 = "2" }
             */

            Utils.CheckNull(key);

            Type           entityType     = typeof(TEntity);
            TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(entityType);

            EnsureEntityHasPrimaryKey(typeDescriptor);

            KeyValuePairList <MemberInfo, object> keyValueMap = new KeyValuePairList <MemberInfo, object>();

            Type keyType = key.GetType();

            if (typeDescriptor.PrimaryKeys.Count == 1 && MappingTypeSystem.IsMappingType(keyType))
            {
                keyValueMap.Add(typeDescriptor.PrimaryKeys[0].MemberInfo, key);
            }
            else
            {
                /*
                 * key: new { Key1 = "1", Key2 = "2" }
                 */

                object multipleKeyObject     = key;
                Type   multipleKeyObjectType = keyType;

                for (int i = 0; i < typeDescriptor.PrimaryKeys.Count; i++)
                {
                    MappingMemberDescriptor keyMemberDescriptor = typeDescriptor.PrimaryKeys[i];
                    MemberInfo keyMember = multipleKeyObjectType.GetProperty(keyMemberDescriptor.MemberInfo.Name);
                    if (keyMember == null)
                    {
                        throw new ArgumentException(string.Format("The input object does not define property for key '{0}'.", keyMemberDescriptor.MemberInfo.Name));
                    }

                    object value = keyMember.GetMemberValue(multipleKeyObject);
                    if (value == null)
                    {
                        throw new ArgumentException(string.Format("The primary key '{0}' could not be null.", keyMemberDescriptor.MemberInfo.Name));
                    }

                    keyValueMap.Add(keyMemberDescriptor.MemberInfo, value);
                }
            }

            ParameterExpression parameter  = Expression.Parameter(entityType, "a");
            Expression          lambdaBody = null;

            foreach (var keyValue in keyValueMap)
            {
                Expression propOrField  = Expression.PropertyOrField(parameter, keyValue.Key.Name);
                Expression wrappedValue = Chloe.Extensions.ExpressionExtension.MakeWrapperAccess(keyValue.Value, keyValue.Key.GetMemberType());
                Expression e            = Expression.Equal(propOrField, wrappedValue);
                lambdaBody = lambdaBody == null ? e : Expression.AndAlso(lambdaBody, e);
            }

            Expression <Func <TEntity, bool> > predicate = Expression.Lambda <Func <TEntity, bool> >(lambdaBody, parameter);

            return(predicate);
        }
예제 #28
0
        static Expression <Func <TEntity, bool> > BuildCondition <TEntity>(object key)
        {
            /*
             * key:
             * 如果实体是单一主键,可以传入的 key 与主键属性类型相同的值,亦可以传一个包含了与实体主键类型相同的属性的对象,如:new { Id = 1 }
             * 如果实体是多主键,则传入的 key 须是包含了与实体主键类型相同的属性的对象,如:new { Key1 = "1", Key2 = "2" }
             */

            Utils.CheckNull(key);

            Type           entityType     = typeof(TEntity);
            TypeDescriptor typeDescriptor = EntityTypeContainer.GetDescriptor(entityType);

            PublicHelper.EnsureHasPrimaryKey(typeDescriptor);

            ParameterExpression parameter     = Expression.Parameter(entityType, "a");
            Expression          conditionBody = null;

            Type keyType = key.GetType();

            if (typeDescriptor.PrimaryKeys.Count == 1 && MappingTypeSystem.IsMappingType(keyType))
            {
                /* a => a.Key == key */

                PropertyDescriptor keyDescriptor = typeDescriptor.PrimaryKeys[0];
                Expression         propOrField   = Expression.PropertyOrField(parameter, keyDescriptor.Property.Name);
                Expression         wrappedValue  = ExpressionExtension.MakeWrapperAccess(key, keyDescriptor.PropertyType);
                conditionBody = Expression.Equal(propOrField, wrappedValue);
            }
            else
            {
                /*
                 * key: new { Key1 = "1", Key2 = "2" }
                 */

                /* a => a.Key1 == key.Key1 && a.Key2 == key.Key2 */

                Type keyObjectType = keyType;
                ConstantExpression keyConstantExp = Expression.Constant(key);
                if (keyObjectType == entityType)
                {
                    foreach (PropertyDescriptor primaryKey in typeDescriptor.PrimaryKeys)
                    {
                        Expression propOrField = Expression.PropertyOrField(parameter, primaryKey.Property.Name);
                        Expression keyValue    = Expression.MakeMemberAccess(keyConstantExp, primaryKey.Property);
                        Expression e           = Expression.Equal(propOrField, keyValue);
                        conditionBody = conditionBody == null ? e : Expression.AndAlso(conditionBody, e);
                    }
                }
                else
                {
                    for (int i = 0; i < typeDescriptor.PrimaryKeys.Count; i++)
                    {
                        PropertyDescriptor keyPropertyDescriptor = typeDescriptor.PrimaryKeys[i];
                        MemberInfo         keyMember             = keyPropertyDescriptor.Property;
                        MemberInfo         inputKeyMember        = keyObjectType.GetMember(keyMember.Name).FirstOrDefault();
                        if (inputKeyMember == null)
                        {
                            throw new ArgumentException(string.Format("The input object does not define property for key '{0}'.", keyMember.Name));
                        }

                        Expression propOrField = Expression.PropertyOrField(parameter, keyMember.Name);
                        Expression keyValueExp = Expression.MakeMemberAccess(keyConstantExp, inputKeyMember);

                        Type keyMemberType = keyMember.GetMemberType();
                        if (inputKeyMember.GetMemberType() != keyMemberType)
                        {
                            keyValueExp = Expression.Convert(keyValueExp, keyMemberType);
                        }
                        Expression e = Expression.Equal(propOrField, keyValueExp);
                        conditionBody = conditionBody == null ? e : Expression.AndAlso(conditionBody, e);
                    }
                }
            }

            Expression <Func <TEntity, bool> > condition = Expression.Lambda <Func <TEntity, bool> >(conditionBody, parameter);

            return(condition);
        }
예제 #29
0
        IDbCommand PrepareCommand(string cmdText, DbParam[] parameters, CommandType cmdType, out List <OutputParameter> outputParameters)
        {
            outputParameters = null;

            IDbCommand cmd = this._dbConnection.CreateCommand();

            cmd.CommandText    = cmdText;
            cmd.CommandType    = cmdType;
            cmd.CommandTimeout = this._commandTimeout;
            if (this.IsInTransaction)
            {
                cmd.Transaction = this._dbTransaction;
            }

            if (parameters != null)
            {
                for (int i = 0; i < parameters.Length; i++)
                {
                    DbParam param = parameters[i];
                    if (param == null)
                    {
                        continue;
                    }

                    if (param.ExplicitParameter != null)/* 如果存在创建好了的 IDbDataParameter,则直接用它。同时也忽视了 DbParam 的其他属性 */
                    {
                        cmd.Parameters.Add(param.ExplicitParameter);
                        continue;
                    }

                    IDbDataParameter parameter = cmd.CreateParameter();
                    parameter.ParameterName = param.Name;

                    Type parameterType;
                    if (param.Value == null || param.Value == DBNull.Value)
                    {
                        parameter.Value = DBNull.Value;
                        parameterType   = param.Type;
                    }
                    else
                    {
                        parameterType = param.Value.GetType();
                        if (parameterType.IsEnum)
                        {
                            parameterType   = Enum.GetUnderlyingType(parameterType);
                            parameter.Value = Convert.ChangeType(param.Value, parameterType);
                        }
                        else
                        {
                            parameter.Value = param.Value;
                        }
                    }

                    if (param.Precision != null)
                    {
                        parameter.Precision = param.Precision.Value;
                    }

                    if (param.Scale != null)
                    {
                        parameter.Scale = param.Scale.Value;
                    }

                    if (param.Size != null)
                    {
                        parameter.Size = param.Size.Value;
                    }

                    if (param.DbType != null)
                    {
                        parameter.DbType = param.DbType.Value;
                    }
                    else
                    {
                        DbType?dbType = MappingTypeSystem.GetDbType(parameterType);
                        if (dbType != null)
                        {
                            parameter.DbType = dbType.Value;
                        }
                    }

                    const int defaultSizeOfStringOutputParameter = 4000;/* 当一个 string 类型输出参数未显示指定 Size 时使用的默认大小。如果有需要更大或者该值不足以满足需求,需显示指定 DbParam.Size 值 */

                    OutputParameter outputParameter = null;
                    if (param.Direction == ParamDirection.Input)
                    {
                        parameter.Direction = ParameterDirection.Input;
                    }
                    else if (param.Direction == ParamDirection.Output)
                    {
                        parameter.Direction = ParameterDirection.Output;
                        param.Value         = null;
                        if (param.Size == null && param.Type == UtilConstants.TypeOfString)
                        {
                            parameter.Size = defaultSizeOfStringOutputParameter;
                        }
                        outputParameter = new OutputParameter(param, parameter);
                    }
                    else if (param.Direction == ParamDirection.InputOutput)
                    {
                        parameter.Direction = ParameterDirection.InputOutput;
                        if (param.Size == null && param.Type == UtilConstants.TypeOfString)
                        {
                            parameter.Size = defaultSizeOfStringOutputParameter;
                        }
                        outputParameter = new OutputParameter(param, parameter);
                    }
                    else
                    {
                        throw new NotSupportedException(string.Format("ParamDirection '{0}' is not supported.", param.Direction));
                    }

                    cmd.Parameters.Add(parameter);

                    if (outputParameter != null)
                    {
                        if (outputParameters == null)
                        {
                            outputParameters = new List <OutputParameter>();
                        }
                        outputParameters.Add(outputParameter);
                    }
                }
            }

            return(cmd);
        }
예제 #30
0
        IDbCommand PrepareCommand(string cmdText, DbParam[] parameters, CommandType cmdType)
        {
            IDbCommand cmd = this._dbConnection.CreateCommand();

            cmd.CommandText    = cmdText;
            cmd.CommandType    = cmdType;
            cmd.CommandTimeout = this._commandTimeout;
            if (this.IsInTransaction)
            {
                cmd.Transaction = this._dbTransaction;
            }

            if (parameters != null)
            {
                for (int i = 0; i < parameters.Length; i++)
                {
                    DbParam param = parameters[i];
                    if (param == null)
                    {
                        continue;
                    }

                    if (param.ExplicitParameter != null)/* 如果存在创建好了的 IDbDataParameter,则直接用它。同时也忽视了 DbParam 的其他属性 */
                    {
                        cmd.Parameters.Add(param.ExplicitParameter);
                        continue;
                    }

                    IDbDataParameter parameter = cmd.CreateParameter();
                    parameter.ParameterName = param.Name;

                    Type parameterType;
                    if (param.Value == null || param.Value == DBNull.Value)
                    {
                        parameter.Value = DBNull.Value;
                        parameterType   = param.Type;
                    }
                    else
                    {
                        parameter.Value = param.Value;
                        parameterType   = param.Value.GetType();
                    }

                    if (param.Precision != null)
                    {
                        parameter.Precision = param.Precision.Value;
                    }

                    if (param.Scale != null)
                    {
                        parameter.Scale = param.Scale.Value;
                    }

                    if (param.Size != null)
                    {
                        parameter.Size = param.Size.Value;
                    }

                    if (param.DbType != null)
                    {
                        parameter.DbType = param.DbType.Value;
                    }
                    else
                    {
                        DbType?dbType = MappingTypeSystem.GetDbType(parameterType);
                        if (dbType != null)
                        {
                            parameter.DbType = dbType.Value;
                        }
                    }
                    cmd.Parameters.Add(parameter);
                }
            }

            return(cmd);
        }