├── .DS_Store ├── .gitignore ├── LICENSE ├── README.md ├── lib ├── Castle.Core.dll ├── Castle.Core.xml ├── MySql.Data.dll ├── Oracle.DataAccess.dll ├── Remotion.Linq.dll ├── Restful.Data.1.0.0.5.nupkg ├── Restful.Data.MySql.dll ├── Restful.Data.Oracle.dll ├── Restful.Data.SqlServer.dll ├── Restful.Data.dll ├── Restful.Linq.dll └── Restful.dll └── src └── Restful ├── References ├── Castle.Core.dll ├── MySql.Data.dll ├── Oracle.DataAccess.dll ├── Remotion.Linq.dll └── nunit.framework.dll ├── Restful.Data.MySql ├── CommandBuilders │ ├── MySqlCommandBuilder.cs │ ├── MySqlDeleteCommandBuilder.cs │ ├── MySqlInsertCommandBuilder.cs │ ├── MySqlLimitPartsAggregator.cs │ ├── MySqlOrderByPartsCommandBuilder.cs │ ├── MySqlQueryCommandBuilder.cs │ ├── MySqlSelectPartsCommandBuilder.cs │ ├── MySqlUpdateCommandBuilder.cs │ └── MySqlWherePartsCommandBuilder.cs ├── Common │ └── Constants.cs ├── Linq │ ├── MySqlDeleteProvider.cs │ ├── MySqlDeleteable.cs │ ├── MySqlInsertProvider.cs │ ├── MySqlInsetable.cs │ ├── MySqlQueryExecutor.cs │ ├── MySqlQueryable.cs │ ├── MySqlUpdateProvider.cs │ └── MySqlUpdateable.cs ├── MySqlSession.cs ├── MySqlSessionProvider.cs ├── MySqlSessionProviderFactory.cs ├── Properties │ └── AssemblyInfo.cs ├── Restful.Data.MySql.csproj └── Visitors │ ├── MySqlOrderByClauseVisitor.cs │ ├── MySqlQueryModelVisitor.cs │ ├── MySqlSelectClauseVisitor.cs │ └── MySqlWhereClauseVisitor.cs ├── Restful.Data.Oracle ├── CommandBuilders │ ├── OracleCommandBuilder.cs │ ├── OracleDeleteCommandBuilder.cs │ ├── OracleInsertCommandBuilder.cs │ ├── OracleLimitPartsAggregator.cs │ ├── OracleOrderByPartsCommandBuilder.cs │ ├── OracleQueryCommandBuilder.cs │ ├── OracleSelectPartsCommandBuilder.cs │ ├── OracleUpdateCommandBuilder.cs │ └── OracleWherePartsCommandBuilder.cs ├── Common │ └── Constants.cs ├── Linq │ ├── OracleDeleteProvider.cs │ ├── OracleDeleteable.cs │ ├── OracleInsertProvider.cs │ ├── OracleInsetable.cs │ ├── OracleQueryExecutor.cs │ ├── OracleQueryable.cs │ ├── OracleUpdateProvider.cs │ └── OracleUpdateable.cs ├── OracleSession.cs ├── OracleSessionProvider.cs ├── OracleSessionProviderFactory.cs ├── Properties │ └── AssemblyInfo.cs ├── Restful.Data.Oracle.csproj └── Visitors │ ├── OracleOrderByClauseVisitor.cs │ ├── OracleQueryModelVisitor.cs │ ├── OracleSelectClauseVisitor.cs │ └── OracleWhereClauseVisitor.cs ├── Restful.Data.SqlServer ├── CommandBuilders │ ├── SqlServerCommandBuilder.cs │ ├── SqlServerDeleteCommandBuilder.cs │ ├── SqlServerInsertCommandBuilder.cs │ ├── SqlServerLimitPartsAggregator.cs │ ├── SqlServerOrderByPartsCommandBuilder.cs │ ├── SqlServerQueryCommandBuilder.cs │ ├── SqlServerSelectPartsCommandBuilder.cs │ ├── SqlServerUpdateCommandBuilder.cs │ └── SqlServerWherePartsCommandBuilder.cs ├── Common │ └── Constants.cs ├── Linq │ ├── SqlServerDeleteProvider.cs │ ├── SqlServerDeleteable.cs │ ├── SqlServerInsertProvider.cs │ ├── SqlServerInsetable.cs │ ├── SqlServerQueryExecutor.cs │ ├── SqlServerQueryable.cs │ ├── SqlServerUpdateProvider.cs │ └── SqlServerUpdateable.cs ├── Properties │ └── AssemblyInfo.cs ├── Restful.Data.SqlServer.csproj ├── SqlServerSession.cs ├── SqlServerSessionProvider.cs ├── SqlServerSessionProviderFactory.cs └── Visitors │ ├── SqlServerOrderByClauseVisitor.cs │ ├── SqlServerQueryModelVisitor.cs │ ├── SqlServerSelectClauseVisitor.cs │ └── SqlServerWhereClauseVisitor.cs ├── Restful.Data ├── Attributes │ ├── AutoIncreaseAttribute.cs │ └── PrimaryKeyAttribute.cs ├── CommandBuilder.cs ├── CommandParameter.cs ├── Dapper │ └── SqlMapper.cs ├── DataPage.cs ├── EntityHelper.cs ├── EntityInterceptor.cs ├── EntityInterceptorFilter.cs ├── EntityInterceptorSelector.cs ├── EntityObject.cs ├── EntityProxyNameScope.cs ├── Extensions │ ├── IDataReaderExtensions.cs │ ├── ISessionExtensions.cs │ ├── IUpdateableGenericExtensions.cs │ ├── ObjectExtensions.cs │ └── PropertyInfoExtensions.cs ├── IEntityObject.cs ├── ISession.cs ├── ISessionProvider.cs ├── ISessionProviderFactory.cs ├── Properties │ └── AssemblyInfo.cs ├── Restful.Data.csproj ├── SessionFactory.cs ├── SessionHelper.cs ├── SessionProvider.cs ├── SessionProviderFactories.cs └── SqlCommandBuilder.cs ├── Restful.Linq ├── Extensions │ ├── IDeleteableExtensions.cs │ ├── IDeleteableGenericExtensions.cs │ ├── IInsertableExtensions.cs │ ├── IInsertableGenericExtensions.cs │ ├── IUpdateableExtensions.cs │ └── IUpdateableGenericExtensions.cs ├── IDeleteProvider.cs ├── IDeleteable.cs ├── IInsertProvider.cs ├── IInsertable.cs ├── IUpdateProvider.cs ├── IUpdateable.cs ├── Properties │ └── AssemblyInfo.cs └── Restful.Linq.csproj ├── Restful.NUnitTests ├── MySqlSessionTest.cs ├── OracleSessionTest .cs ├── Restful.NUnitTests.csproj ├── SqlServerSessionTest.cs ├── app.config └── bin │ └── Release │ ├── Castle.Core.dll │ ├── Castle.Core.xml │ ├── MySql.Data.dll │ ├── Oracle.DataAccess.dll │ ├── Remotion.Linq.dll │ ├── Restful.Data.MySql.dll │ ├── Restful.Data.Oracle.dll │ ├── Restful.Data.SqlServer.dll │ ├── Restful.Data.dll │ ├── Restful.Linq.dll │ ├── Restful.NUnitTests.dll │ ├── Restful.NUnitTests.dll.config │ ├── Restful.dll │ └── nunit.framework.dll ├── Restful.sln ├── Restful.userprefs ├── Restful ├── Collections │ └── Generic │ │ └── ThreadSafeDictionary.cs ├── Extensions │ ├── ExpressionExtensions.cs │ ├── IEnumerableGenericExtensions.cs │ ├── ObjectExtensions.cs │ ├── PropertyInfoExtensions.cs │ ├── StringExtensions.cs │ └── TypeExtensions.cs ├── Properties │ └── AssemblyInfo.cs ├── Reflection │ └── Emit │ │ └── DynamicHelper.cs └── Restful.csproj └── 实体生成器模板.cmt /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linli8/Restful/16013bf91d508b88e3819e533b8517a6483075b2/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | debug 2 | obj 3 | *.user 4 | *.suo 5 | *.mdb 6 | *.pdb -------------------------------------------------------------------------------- /lib/Castle.Core.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linli8/Restful/16013bf91d508b88e3819e533b8517a6483075b2/lib/Castle.Core.dll -------------------------------------------------------------------------------- /lib/MySql.Data.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linli8/Restful/16013bf91d508b88e3819e533b8517a6483075b2/lib/MySql.Data.dll -------------------------------------------------------------------------------- /lib/Oracle.DataAccess.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linli8/Restful/16013bf91d508b88e3819e533b8517a6483075b2/lib/Oracle.DataAccess.dll -------------------------------------------------------------------------------- /lib/Remotion.Linq.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linli8/Restful/16013bf91d508b88e3819e533b8517a6483075b2/lib/Remotion.Linq.dll -------------------------------------------------------------------------------- /lib/Restful.Data.1.0.0.5.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linli8/Restful/16013bf91d508b88e3819e533b8517a6483075b2/lib/Restful.Data.1.0.0.5.nupkg -------------------------------------------------------------------------------- /lib/Restful.Data.MySql.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linli8/Restful/16013bf91d508b88e3819e533b8517a6483075b2/lib/Restful.Data.MySql.dll -------------------------------------------------------------------------------- /lib/Restful.Data.Oracle.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linli8/Restful/16013bf91d508b88e3819e533b8517a6483075b2/lib/Restful.Data.Oracle.dll -------------------------------------------------------------------------------- /lib/Restful.Data.SqlServer.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linli8/Restful/16013bf91d508b88e3819e533b8517a6483075b2/lib/Restful.Data.SqlServer.dll -------------------------------------------------------------------------------- /lib/Restful.Data.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linli8/Restful/16013bf91d508b88e3819e533b8517a6483075b2/lib/Restful.Data.dll -------------------------------------------------------------------------------- /lib/Restful.Linq.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linli8/Restful/16013bf91d508b88e3819e533b8517a6483075b2/lib/Restful.Linq.dll -------------------------------------------------------------------------------- /lib/Restful.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linli8/Restful/16013bf91d508b88e3819e533b8517a6483075b2/lib/Restful.dll -------------------------------------------------------------------------------- /src/Restful/References/Castle.Core.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linli8/Restful/16013bf91d508b88e3819e533b8517a6483075b2/src/Restful/References/Castle.Core.dll -------------------------------------------------------------------------------- /src/Restful/References/MySql.Data.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linli8/Restful/16013bf91d508b88e3819e533b8517a6483075b2/src/Restful/References/MySql.Data.dll -------------------------------------------------------------------------------- /src/Restful/References/Oracle.DataAccess.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linli8/Restful/16013bf91d508b88e3819e533b8517a6483075b2/src/Restful/References/Oracle.DataAccess.dll -------------------------------------------------------------------------------- /src/Restful/References/Remotion.Linq.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linli8/Restful/16013bf91d508b88e3819e533b8517a6483075b2/src/Restful/References/Remotion.Linq.dll -------------------------------------------------------------------------------- /src/Restful/References/nunit.framework.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linli8/Restful/16013bf91d508b88e3819e533b8517a6483075b2/src/Restful/References/nunit.framework.dll -------------------------------------------------------------------------------- /src/Restful/Restful.Data.MySql/CommandBuilders/MySqlCommandBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Restful.Data.MySql.Common; 3 | using System.Collections.Generic; 4 | 5 | namespace Restful.Data.MySql.CommandBuilders 6 | { 7 | public class MySqlCommandBuilder : CommandBuilder 8 | { 9 | private string sql; 10 | 11 | #region implemented abstract members of CommandBuilder 12 | 13 | public override string Sql 14 | { 15 | get 16 | { 17 | return this.sql; 18 | } 19 | set 20 | { 21 | this.sql = value; 22 | } 23 | } 24 | 25 | public override string AddParameter( object value ) 26 | { 27 | string parameterName = string.Format( "{0}P{1}", Constants.ParameterPrefix, this.parameters.Count ); 28 | 29 | this.AddParameter( parameterName, value ); 30 | 31 | return parameterName; 32 | } 33 | 34 | #endregion 35 | 36 | public MySqlCommandBuilder() : base() 37 | { 38 | } 39 | 40 | public MySqlCommandBuilder( string sql ) : this() 41 | { 42 | this.sql = sql; 43 | } 44 | 45 | public MySqlCommandBuilder( IDictionary parameters ) : base( parameters ) 46 | { 47 | } 48 | 49 | public MySqlCommandBuilder( string sql, IDictionary parameters ) : this( parameters ) 50 | { 51 | this.sql = sql; 52 | } 53 | } 54 | } 55 | 56 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.MySql/CommandBuilders/MySqlDeleteCommandBuilder.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using Restful.Data.MySql.Common; 3 | 4 | namespace Restful.Data.MySql.CommandBuilders 5 | { 6 | public class MySqlDeleteCommandBuilder : MySqlCommandBuilder 7 | { 8 | private string tableName { get; set; } 9 | 10 | public string WhereParts { get; set; } 11 | 12 | public MySqlDeleteCommandBuilder( string tableName ) : base() 13 | { 14 | this.tableName = tableName; 15 | } 16 | 17 | public override string ToString() 18 | { 19 | var builder = new StringBuilder(); 20 | 21 | builder.Append( "delete from " ); 22 | builder.AppendFormat( "{0}{1}{2} ", Constants.LeftQuote, this.tableName, Constants.RightQuote ); 23 | 24 | if( string.IsNullOrEmpty( this.WhereParts ) == false ) 25 | { 26 | builder.AppendFormat( "where {0}", this.WhereParts ); 27 | } 28 | 29 | builder.Append( ";" ); 30 | 31 | return builder.ToString(); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.MySql/CommandBuilders/MySqlInsertCommandBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading; 4 | using System.Text; 5 | using Restful.Data.MySql.Common; 6 | 7 | namespace Restful.Data.MySql.CommandBuilders 8 | { 9 | public class MySqlInsertCommandBuilder : MySqlCommandBuilder 10 | { 11 | private string tableName { get; set; } 12 | 13 | private readonly IList columns; 14 | 15 | public MySqlInsertCommandBuilder( string tableName ) : base() 16 | { 17 | this.tableName = tableName; 18 | this.columns = new List(); 19 | } 20 | 21 | public void AddColumn( string columnName, object value ) 22 | { 23 | this.AddParameter( value ); 24 | 25 | this.columns.Add( string.Format( "{0}{1}{2}", Constants.LeftQuote, columnName, Constants.RightQuote ) ); 26 | } 27 | 28 | public override string ToString() 29 | { 30 | StringBuilder builder = new StringBuilder(); 31 | 32 | builder.AppendFormat( "insert into {0}{1}{2} ", Constants.LeftQuote, this.tableName, Constants.RightQuote ); 33 | builder.AppendFormat( "( {0} ) ", string.Join( ", ", this.columns ) ); 34 | builder.AppendFormat( "values ( {0} );", string.Join( ", ", this.parameters.Keys ) ); 35 | 36 | return builder.ToString(); 37 | } 38 | } 39 | } 40 | 41 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.MySql/CommandBuilders/MySqlLimitPartsAggregator.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace Restful.Data.MySql.CommandBuilders 3 | { 4 | internal class MySqlLimitPartsAggregator 5 | { 6 | public int From { get; set; } 7 | 8 | public int Count { get; set; } 9 | 10 | public MySqlLimitPartsAggregator() 11 | { 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.MySql/CommandBuilders/MySqlOrderByPartsCommandBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | 4 | namespace Restful.Data.MySql.CommandBuilders 5 | { 6 | public class MySqlOrderByPartsCommandBuilder : MySqlCommandBuilder 7 | { 8 | public StringBuilder OrderByParts { get; private set; } 9 | 10 | public MySqlOrderByPartsCommandBuilder() : base() 11 | { 12 | this.OrderByParts = new StringBuilder(); 13 | } 14 | 15 | public override string ToString() 16 | { 17 | return this.OrderByParts.ToString(); 18 | } 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.MySql/CommandBuilders/MySqlQueryCommandBuilder.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Text; 3 | 4 | namespace Restful.Data.MySql.CommandBuilders 5 | { 6 | internal class MySqlQueryCommandBuilder : MySqlCommandBuilder 7 | { 8 | public bool IsDistinct { get; set; } 9 | 10 | public string SelectPart { get; set; } 11 | 12 | public IList FromParts { get; private set; } 13 | 14 | public IList WhereParts { get; private set; } 15 | 16 | public IList OrderByParts { get; private set; } 17 | 18 | public MySqlLimitPartsAggregator LimitParts { get; private set; } 19 | 20 | /// 21 | /// 22 | /// 23 | public MySqlQueryCommandBuilder() : base() 24 | { 25 | this.FromParts = new List(); 26 | this.WhereParts = new List(); 27 | this.OrderByParts = new List(); 28 | this.LimitParts = new MySqlLimitPartsAggregator(); 29 | } 30 | 31 | public override string ToString() 32 | { 33 | var builder = new StringBuilder(); 34 | 35 | builder.Append( "select " ); 36 | 37 | if( this.IsDistinct ) 38 | { 39 | builder.Append( "distinct " ); 40 | } 41 | 42 | builder.Append( this.SelectPart ); 43 | 44 | builder.AppendFormat( " from {0} ", string.Join( ", ", this.FromParts ) ); 45 | 46 | if( this.WhereParts.Count > 0 ) 47 | { 48 | builder.AppendFormat( "where {0} ", string.Join( " and ", this.WhereParts ) ); 49 | } 50 | 51 | if( OrderByParts.Count > 0 ) 52 | { 53 | builder.AppendFormat( "order by {0} ", string.Join( ", ", OrderByParts ) ); 54 | } 55 | 56 | if( this.LimitParts.From != 0 || this.LimitParts.Count != 0 ) 57 | { 58 | builder.AppendFormat( "limit {0},{1}", this.LimitParts.From, this.LimitParts.Count ); 59 | } 60 | 61 | return builder.ToString(); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.MySql/CommandBuilders/MySqlSelectPartsCommandBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | 4 | namespace Restful.Data.MySql.CommandBuilders 5 | { 6 | public class MySqlSelectPartsCommandBuilder : MySqlCommandBuilder 7 | { 8 | public StringBuilder SelectPartsBuilder { get; private set; } 9 | 10 | public MySqlSelectPartsCommandBuilder() : base() 11 | { 12 | this.SelectPartsBuilder = new StringBuilder(); 13 | } 14 | 15 | public override string ToString() 16 | { 17 | return this.SelectPartsBuilder.ToString(); 18 | } 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.MySql/CommandBuilders/MySqlUpdateCommandBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Restful.Data.MySql.Common; 4 | using System.Text; 5 | 6 | namespace Restful.Data.MySql.CommandBuilders 7 | { 8 | public class MySqlUpdateCommandBuilder : MySqlCommandBuilder 9 | { 10 | private string tableName { get; set; } 11 | 12 | private readonly IList columns; 13 | 14 | public string WhereParts { get; set; } 15 | 16 | public MySqlUpdateCommandBuilder( string tableName ) : base() 17 | { 18 | this.tableName = tableName; 19 | this.columns = new List(); 20 | } 21 | 22 | public void AddColumn( string columnName, object value ) 23 | { 24 | string parameterName = this.AddParameter( value ); 25 | 26 | this.columns.Add( 27 | string.Format( "{0}{1}{2} = {3}", Constants.LeftQuote, columnName, Constants.RightQuote, parameterName 28 | ) ); 29 | } 30 | 31 | public override string ToString() 32 | { 33 | StringBuilder builder = new StringBuilder(); 34 | 35 | builder.AppendFormat( "update {0}{1}{2} set ", Constants.LeftQuote, this.tableName, Constants.RightQuote ); 36 | builder.AppendFormat( "{0} ", string.Join( ", ", this.columns ) ); 37 | 38 | if( string.IsNullOrEmpty( this.WhereParts ) == false ) 39 | { 40 | builder.AppendFormat( "where {0};", this.WhereParts ); 41 | } 42 | 43 | return builder.ToString(); 44 | } 45 | } 46 | } 47 | 48 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.MySql/CommandBuilders/MySqlWherePartsCommandBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Restful.Data.MySql.Common; 4 | using System.Text; 5 | 6 | namespace Restful.Data.MySql.CommandBuilders 7 | { 8 | public class MySqlWherePartsCommandBuilder : MySqlCommandBuilder 9 | { 10 | public StringBuilder WherePartsBuilder { get; private set; } 11 | 12 | public MySqlWherePartsCommandBuilder() : base() 13 | { 14 | this.WherePartsBuilder = new StringBuilder(); 15 | } 16 | 17 | public MySqlWherePartsCommandBuilder( IDictionary parameters ) : base( parameters ) 18 | { 19 | this.WherePartsBuilder = new StringBuilder(); 20 | } 21 | 22 | public override string ToString() 23 | { 24 | return this.WherePartsBuilder.ToString(); 25 | } 26 | } 27 | } 28 | 29 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.MySql/Common/Constants.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Restful.Data.MySql.Common 7 | { 8 | /// 9 | /// 定义程序集中所用的常量 10 | /// 11 | internal class Constants 12 | { 13 | /// 14 | /// 左引用符号 15 | /// 16 | public const string LeftQuote = "`"; 17 | 18 | /// 19 | /// 右引用符号 20 | /// 21 | public const string RightQuote = "`"; 22 | 23 | /// 24 | /// 参数前缀 25 | /// 26 | public const string ParameterPrefix = "@"; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.MySql/Linq/MySqlDeleteProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Restful.Linq; 3 | using System.Linq.Expressions; 4 | using Remotion.Linq.Parsing.ExpressionTreeVisitors; 5 | using Restful.Data.MySql.Visitors; 6 | using Restful.Data.MySql.CommandBuilders; 7 | 8 | namespace Restful.Data.MySql.Linq 9 | { 10 | public class MySqlDeleteProvider : IDeleteProvider 11 | { 12 | private readonly ISessionProvider sessionProvider; 13 | 14 | public MySqlDeleteProvider( ISessionProvider sessionProvider ) 15 | { 16 | this.sessionProvider = sessionProvider; 17 | } 18 | 19 | #region IDeleteProvider implementation 20 | 21 | public IDeleteable CreateDelete( Type elementType ) 22 | { 23 | return (IDeleteable)Activator.CreateInstance( typeof( MySqlDeleteable<> ).MakeGenericType( elementType ), new object[] { this, elementType } ); 24 | } 25 | 26 | public int Execute( Type elementType, Expression predicate ) 27 | { 28 | MySqlDeleteCommandBuilder deleteBuilder = new MySqlDeleteCommandBuilder( elementType.Name ); 29 | 30 | if( predicate != null ) 31 | { 32 | MySqlWherePartsCommandBuilder whereBuilder = new MySqlWherePartsCommandBuilder( deleteBuilder.Parameters ); 33 | 34 | Expression expression = PartialEvaluatingExpressionTreeVisitor.EvaluateIndependentSubtrees( predicate ); 35 | 36 | MySqlWhereClauseVisitor visitor = new MySqlWhereClauseVisitor(); 37 | 38 | visitor.Translate( expression, whereBuilder ); 39 | 40 | deleteBuilder.WhereParts = whereBuilder.WherePartsBuilder.ToString(); 41 | } 42 | 43 | this.sessionProvider.ExecutedCommandBuilder = deleteBuilder; 44 | 45 | return this.sessionProvider.ExecuteNonQuery( deleteBuilder ); 46 | } 47 | 48 | public IDeleteable CreateDelete() 49 | { 50 | return new MySqlDeleteable( this ); 51 | } 52 | 53 | public int Execute( Expression predicate ) 54 | { 55 | return Execute( typeof( T ), predicate ); 56 | } 57 | 58 | #endregion 59 | } 60 | } 61 | 62 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.MySql/Linq/MySqlDeleteable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq.Expressions; 4 | using Remotion.Linq.Parsing.ExpressionTreeVisitors; 5 | using Restful.Linq; 6 | using Restful.Data.MySql.CommandBuilders; 7 | using Restful.Data.MySql.Visitors; 8 | 9 | namespace Restful.Data.MySql.Linq 10 | { 11 | public class MySqlDeleteable : IDeleteable 12 | { 13 | private readonly Type elementType; 14 | private readonly IDeleteProvider provider; 15 | 16 | public MySqlDeleteable( IDeleteProvider provider ) 17 | { 18 | this.provider = provider; 19 | this.elementType = typeof( T ); 20 | } 21 | 22 | public MySqlDeleteable( IDeleteProvider provider, Type elementType ) 23 | { 24 | this.provider = provider; 25 | this.elementType = elementType; 26 | } 27 | 28 | #region IDeleteable implementation 29 | 30 | public Type ElementType 31 | { 32 | get 33 | { 34 | return this.elementType; 35 | } 36 | } 37 | 38 | public Expression Predicate { get; set; } 39 | 40 | public IDeleteProvider Provider 41 | { 42 | get 43 | { 44 | return this.provider; 45 | } 46 | } 47 | 48 | #endregion 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.MySql/Linq/MySqlInsertProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Linq.Expressions; 5 | using System.Text; 6 | using Remotion.Linq.Parsing.ExpressionTreeVisitors; 7 | using Restful.Linq; 8 | using Restful.Data.MySql.CommandBuilders; 9 | using Restful.Data.MySql.Common; 10 | using Restful.Data.MySql.Visitors; 11 | 12 | namespace Restful.Data.MySql.Linq 13 | { 14 | public class MySqlInsertProvider : IInsertProvider 15 | { 16 | private readonly ISessionProvider sessionProvider; 17 | 18 | public MySqlInsertProvider( ISessionProvider sessionProvider ) 19 | { 20 | this.sessionProvider = sessionProvider; 21 | } 22 | 23 | public IInsertable CreateInsert( Type elementType ) 24 | { 25 | return (IInsertable)Activator.CreateInstance( typeof( MySqlInsertable<> ).MakeGenericType( elementType ), new object[] { this, elementType } ); 26 | } 27 | 28 | public int Execute( Type elementType, IDictionary properties ) 29 | { 30 | MySqlInsertCommandBuilder insertBuilder = new MySqlInsertCommandBuilder( elementType.Name ); 31 | 32 | foreach( var item in properties ) 33 | { 34 | insertBuilder.AddColumn( item.Key.Member.Name, item.Value ); 35 | } 36 | 37 | this.sessionProvider.ExecutedCommandBuilder = insertBuilder; 38 | 39 | return this.sessionProvider.ExecuteNonQuery( insertBuilder ); 40 | } 41 | 42 | public IInsertable CreateInsert() 43 | { 44 | return new MySqlInsertable( this ); 45 | } 46 | 47 | public int Execute( IDictionary properties ) 48 | { 49 | return this.Execute( typeof( T ), properties ); 50 | } 51 | } 52 | } 53 | 54 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.MySql/Linq/MySqlInsetable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | using Remotion.Linq.Parsing.ExpressionTreeVisitors; 4 | using Restful.Data.MySql.CommandBuilders; 5 | using Restful.Data.MySql.Visitors; 6 | using System.Collections.Generic; 7 | using Restful.Linq; 8 | 9 | namespace Restful.Data.MySql.Linq 10 | { 11 | public class MySqlInsertable : IInsertable 12 | { 13 | private readonly Type elementType; 14 | private readonly IDictionary properties; 15 | private readonly IInsertProvider provider; 16 | 17 | public MySqlInsertable( IInsertProvider provider ) 18 | { 19 | this.provider = provider; 20 | this.elementType = typeof( T ); 21 | this.properties = new Dictionary(); 22 | } 23 | 24 | public MySqlInsertable( IInsertProvider provider, Type elementType ) 25 | { 26 | this.provider = provider; 27 | this.elementType = elementType; 28 | this.properties = new Dictionary(); 29 | } 30 | 31 | #region IInsertable implementation 32 | 33 | public Type ElementType 34 | { 35 | get 36 | { 37 | return this.elementType; 38 | } 39 | } 40 | 41 | public IDictionary Properties 42 | { 43 | get 44 | { 45 | return this.properties; 46 | } 47 | } 48 | 49 | 50 | public IInsertProvider Provider 51 | { 52 | get 53 | { 54 | return this.provider; 55 | } 56 | } 57 | 58 | #endregion 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.MySql/Linq/MySqlQueryExecutor.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Data; 3 | using System.Data.Common; 4 | using Remotion.Linq; 5 | using Restful.Data.MySql.Visitors; 6 | using System; 7 | 8 | namespace Restful.Data.MySql.Linq 9 | { 10 | public class MySqlQueryExecutor : IQueryExecutor 11 | { 12 | protected ISessionProvider provider; 13 | 14 | public MySqlQueryExecutor( ISessionProvider provider ) 15 | { 16 | this.provider = provider; 17 | } 18 | 19 | #region ExecuteCollection 20 | 21 | /// 22 | /// 执行查询,并返回 IEnumerable 对象 23 | /// 24 | /// 25 | /// 26 | /// 27 | public IEnumerable ExecuteCollection( QueryModel queryModel ) 28 | { 29 | MySqlQueryModelVisitor queryModelVisitor = new MySqlQueryModelVisitor(); 30 | 31 | var command = queryModelVisitor.Translate( queryModel ); 32 | 33 | this.provider.ExecutedCommandBuilder = command; 34 | 35 | using( IDataReader reader = this.provider.ExecuteDataReader( command ) ) 36 | { 37 | var tuple = reader.GetDeserializerState(); 38 | 39 | while( reader.Read() ) 40 | { 41 | yield return (T)tuple.Func( reader ); 42 | } 43 | } 44 | } 45 | 46 | #endregion 47 | 48 | #region ExecuteScalar 49 | 50 | /// 51 | /// 执行查询,并返回第一行第一列 52 | /// 53 | /// 54 | /// 55 | /// 56 | public T ExecuteScalar( QueryModel queryModel ) 57 | { 58 | MySqlQueryModelVisitor queryModelVisitor = new MySqlQueryModelVisitor(); 59 | 60 | var command = queryModelVisitor.Translate( queryModel ); 61 | 62 | this.provider.ExecutedCommandBuilder = command; 63 | 64 | return this.provider.ExecuteScalar( command ); 65 | } 66 | 67 | #endregion 68 | 69 | #region ExecuteSingle 70 | 71 | /// 72 | /// 执行查询,并返回单个对象 73 | /// 74 | /// 75 | /// 76 | /// 77 | /// 78 | public T ExecuteSingle( QueryModel queryModel, bool returnDefaultWhenEmpty ) 79 | { 80 | MySqlQueryModelVisitor queryModelVisitor = new MySqlQueryModelVisitor(); 81 | 82 | var command = queryModelVisitor.Translate( queryModel ); 83 | 84 | this.provider.ExecutedCommandBuilder = command; 85 | 86 | using( IDataReader reader = this.provider.ExecuteDataReader( command ) ) 87 | { 88 | bool isExists = reader.Read(); 89 | 90 | // 如果不存在查询记录 91 | if( isExists == false ) 92 | { 93 | // 如果可以默认 94 | if( returnDefaultWhenEmpty ) 95 | { 96 | return default( T ); 97 | } 98 | else 99 | { 100 | throw new InvalidOperationException( "未查询出满足条件的任何记录。" ); 101 | } 102 | } 103 | 104 | var tuple = reader.GetDeserializerState(); 105 | 106 | return (T)tuple.Func( reader ); 107 | } 108 | } 109 | 110 | #endregion 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.MySql/Linq/MySqlQueryable.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Linq.Expressions; 3 | using Remotion.Linq; 4 | using Remotion.Linq.Parsing.Structure; 5 | 6 | namespace Restful.Data.MySql.Linq 7 | { 8 | public class MySqlQueryable : QueryableBase 9 | { 10 | public MySqlQueryable( IQueryParser queryParser, IQueryExecutor executor ) 11 | : base( new DefaultQueryProvider( typeof( MySqlQueryable<> ), queryParser, executor ) ) 12 | { 13 | } 14 | 15 | public MySqlQueryable( IQueryProvider provider, Expression expression ) 16 | : base( provider, expression ) 17 | { 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.MySql/Linq/MySqlUpdateProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Restful.Linq; 3 | using System.Linq.Expressions; 4 | using Remotion.Linq.Parsing.ExpressionTreeVisitors; 5 | using Restful.Data.MySql.Visitors; 6 | using Restful.Data.MySql.CommandBuilders; 7 | using System.Collections.Generic; 8 | using System.Text; 9 | using System.Collections; 10 | using Restful.Data.MySql.Common; 11 | 12 | namespace Restful.Data.MySql.Linq 13 | { 14 | public class MySqlUpdateProvider : IUpdateProvider 15 | { 16 | private readonly ISessionProvider sessionProvider; 17 | 18 | public MySqlUpdateProvider( ISessionProvider sessionProvider ) 19 | { 20 | this.sessionProvider = sessionProvider; 21 | } 22 | 23 | public IUpdateable CreateUpdate( Type elementType ) 24 | { 25 | return (IUpdateable)Activator.CreateInstance( typeof( MySqlUpdateable<> ).MakeGenericType( elementType ), new object[] { this, elementType } ); 26 | } 27 | 28 | public IUpdateable CreateUpdate() 29 | { 30 | return new MySqlUpdateable( this ); 31 | } 32 | 33 | public int Execute( Type elementType, IDictionary properties, Expression predicate ) 34 | { 35 | MySqlUpdateCommandBuilder updateBuilder = new MySqlUpdateCommandBuilder( elementType.Name ); 36 | 37 | foreach( var item in properties ) 38 | { 39 | updateBuilder.AddColumn( item.Key.Member.Name, item.Value ); 40 | } 41 | 42 | if( predicate != null ) 43 | { 44 | MySqlWherePartsCommandBuilder whereBuider = new MySqlWherePartsCommandBuilder( updateBuilder.Parameters ); 45 | 46 | Expression expression = PartialEvaluatingExpressionTreeVisitor.EvaluateIndependentSubtrees( predicate ); 47 | 48 | MySqlWhereClauseVisitor visitor = new MySqlWhereClauseVisitor(); 49 | 50 | visitor.Translate( expression, whereBuider ); 51 | 52 | updateBuilder.WhereParts = whereBuider.WherePartsBuilder.ToString(); 53 | } 54 | 55 | this.sessionProvider.ExecutedCommandBuilder = updateBuilder; 56 | 57 | return this.sessionProvider.ExecuteNonQuery( updateBuilder ); 58 | } 59 | 60 | public int Execute( IDictionary properties, Expression predicate ) 61 | { 62 | return this.Execute( typeof( T ), properties, predicate ); 63 | } 64 | 65 | } 66 | } 67 | 68 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.MySql/MySqlSession.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Restful.Data.MySql 7 | { 8 | public class MySqlSession : ISession 9 | { 10 | private MySqlSessionProvider provider; 11 | 12 | public MySqlSession( ISessionProviderFactory factory, string connectionStr ) 13 | { 14 | this.provider = new MySqlSessionProvider( factory, connectionStr ); 15 | } 16 | 17 | public int CommandTimeout 18 | { 19 | get 20 | { 21 | return this.provider.CommandTimeout; 22 | } 23 | set 24 | { 25 | this.provider.CommandTimeout = value; 26 | } 27 | } 28 | 29 | public ISessionProvider Provider 30 | { 31 | get { return this.provider; } 32 | } 33 | 34 | public void Dispose() 35 | { 36 | this.provider.Dispose(); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.MySql/MySqlSessionProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Data; 4 | using System.Data.Common; 5 | using System.Diagnostics; 6 | using System.Linq; 7 | using System.Reflection; 8 | using System.Text; 9 | using MySql.Data.MySqlClient; 10 | using Remotion.Linq.Parsing.Structure; 11 | using Restful; 12 | using Restful.Data.Attributes; 13 | using Restful.Data.MySql.Common; 14 | using Restful.Data.MySql.Linq; 15 | 16 | namespace Restful.Data.MySql 17 | { 18 | public class MySqlSessionProvider : SessionProvider 19 | { 20 | #region MySqlSessionProvider 21 | 22 | /// 23 | /// 构造函数 24 | /// 25 | /// 26 | public MySqlSessionProvider( ISessionProviderFactory factory, string connectionStr ) : base( factory, connectionStr ) 27 | { 28 | 29 | } 30 | 31 | #endregion 32 | 33 | #region ExecuteDataPage 34 | 35 | /// 36 | /// 执行分页查询 37 | /// 38 | /// SQL 语句 39 | /// 页索引 40 | /// 页大小 41 | /// 排序字段 42 | /// 参数列表 43 | /// 分页查询结果 44 | public override DataPage ExecuteDataPage( CommandBuilder command, int pageIndex, int pageSize, string orderBy ) 45 | { 46 | if( string.IsNullOrEmpty( orderBy ) ) 47 | { 48 | throw new ArgumentNullException( "orderBy" ); 49 | } 50 | 51 | DataPage dataPage = new DataPage( pageIndex, pageSize ); 52 | 53 | #region 查询满足条件的条目数量 54 | string queryItemCountSql = string.Format( "SELECT COUNT(*) FROM ( {0} ) T1", command.ToString() ); 55 | 56 | dataPage.ItemCount = this.ExecuteScalar( new Restful.Data.MySql.CommandBuilders.MySqlCommandBuilder( queryItemCountSql, command.Parameters ) ); 57 | 58 | if( dataPage.ItemCount == 0 ) // 如果满足条件的数据条目数量为零,则重置页索引为 1 59 | { 60 | dataPage.PageIndex = 1; 61 | } 62 | else if( dataPage.PageIndex > dataPage.PageCount ) // 如果指定的页索引大于查询直接总页数,则重置页索引为总页数 63 | { 64 | dataPage.PageIndex = dataPage.PageCount; 65 | } 66 | #endregion 67 | 68 | #region 查询最终的结果集 69 | 70 | string limitFrom = string.Format( "{0}LimitFrom", Constants.ParameterPrefix ); 71 | string limitCount = string.Format( "{0}LimitCount", Constants.ParameterPrefix ); 72 | 73 | command.Parameters.Add( limitFrom, ( dataPage.PageIndex - 1 ) * dataPage.PageSize ); 74 | command.Parameters.Add( limitCount, dataPage.PageSize ); 75 | 76 | string queryItemSql = string.Format( "SELECT * FROM ( {0} ) T ORDER BY {1} LIMIT {2}, {3}", command.ToString(), orderBy, limitFrom, limitCount ); 77 | 78 | dataPage.Data = this.ExecuteDataTable( new Restful.Data.MySql.CommandBuilders.MySqlCommandBuilder( queryItemSql, command.Parameters ) ); 79 | #endregion 80 | 81 | return dataPage; 82 | } 83 | 84 | #endregion 85 | 86 | #region GetIdentifier 87 | 88 | /// 89 | /// 获取最新插入数据的自增ID 90 | /// 91 | /// 92 | /// 93 | public override T GetIdentifier() 94 | { 95 | return this.ExecuteScalar( new Restful.Data.MySql.CommandBuilders.MySqlCommandBuilder( "SELECT LAST_INSERT_ID();" ) ); 96 | } 97 | 98 | #endregion 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.MySql/MySqlSessionProviderFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Data; 6 | using System.Data.Common; 7 | using MySql.Data.MySqlClient; 8 | using Restful.Data.MySql.Linq; 9 | using Remotion.Linq.Parsing.Structure; 10 | using Remotion.Linq; 11 | using Restful.Data.MySql.CommandBuilders; 12 | using Restful.Data.MySql.Visitors; 13 | using Restful.Linq; 14 | 15 | namespace Restful.Data.MySql 16 | { 17 | public class MySqlSessionProviderFactory : ISessionProviderFactory 18 | { 19 | public CommandBuilder CreateCommandBuilder() 20 | { 21 | return new Restful.Data.MySql.CommandBuilders.MySqlCommandBuilder(); 22 | } 23 | 24 | public IUpdateProvider CreateUpdateProvider( ISessionProvider provider ) 25 | { 26 | return new MySqlUpdateProvider( provider ); 27 | } 28 | 29 | public IInsertProvider CreateInsertProvider( ISessionProvider provider ) 30 | { 31 | return new MySqlInsertProvider( provider ); 32 | } 33 | 34 | public IDeleteProvider CreateDeleteProvider( ISessionProvider provider ) 35 | { 36 | return new MySqlDeleteProvider( provider ); 37 | } 38 | 39 | public ISession CreateSession( string connectionStr ) 40 | { 41 | return new MySqlSession( this, connectionStr ); 42 | } 43 | 44 | public DbConnection CreateConnection( string connectionStr ) 45 | { 46 | return new MySqlConnection( connectionStr ); 47 | } 48 | 49 | public DbDataAdapter CreateDataAdapter() 50 | { 51 | return new MySqlDataAdapter(); 52 | } 53 | 54 | public IQueryable CreateQueryable( ISessionProvider provider ) 55 | { 56 | return new MySqlQueryable( QueryParser.CreateDefault(), new MySqlQueryExecutor( provider ) ); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.MySql/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的常规信息通过以下 6 | // 特性集控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle("Restful.Data.MySql")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Restful.Data.MySql")] 13 | [assembly: AssemblyCopyright("Copyright © 2014")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // 将 ComVisible 设置为 false 使此程序集中的类型 18 | // 对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型, 19 | // 则将该类型上的 ComVisible 特性设置为 true。 20 | [assembly: ComVisible(false)] 21 | 22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 23 | [assembly: Guid("b44d5a49-0a0d-4872-94fd-a3a52890f911")] 24 | 25 | // 程序集的版本信息由下面四个值组成: 26 | // 27 | // 主版本 28 | // 次版本 29 | // 生成号 30 | // 修订号 31 | // 32 | // 可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值, 33 | // 方法是按如下所示使用“*”: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.MySql/Visitors/MySqlOrderByClauseVisitor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq.Expressions; 4 | using System.Text; 5 | using Remotion.Linq.Clauses.ExpressionTreeVisitors; 6 | using Remotion.Linq.Clauses.Expressions; 7 | using Remotion.Linq.Parsing; 8 | using Restful.Data.MySql.Common; 9 | using Restful.Data.MySql.CommandBuilders; 10 | 11 | namespace Restful.Data.MySql.Visitors 12 | { 13 | internal class MySqlOrderByClauseVisitor : ThrowingExpressionTreeVisitor 14 | { 15 | private MySqlOrderByPartsCommandBuilder commandBuilder; 16 | 17 | #region OrderByClauseVisitor 18 | 19 | /// 20 | /// 构造函数 21 | /// 22 | public MySqlOrderByClauseVisitor() 23 | { 24 | } 25 | 26 | #endregion 27 | 28 | #region Translate 29 | 30 | /// 31 | /// 翻译表达式 32 | /// 33 | /// 34 | public void Translate( Expression expression, MySqlOrderByPartsCommandBuilder commandBuilder ) 35 | { 36 | this.commandBuilder = commandBuilder; 37 | 38 | this.VisitExpression( expression ); 39 | } 40 | 41 | #endregion 42 | 43 | #region VisitQuerySourceReferenceExpression 44 | 45 | /// 46 | /// 解析查询源引用表达式 47 | /// 48 | /// 49 | /// 50 | protected override Expression VisitQuerySourceReferenceExpression( QuerySourceReferenceExpression expression ) 51 | { 52 | this.commandBuilder.OrderByParts.Append( expression.ReferencedQuerySource.ItemName.ToLower() ); 53 | 54 | return expression; 55 | } 56 | 57 | #endregion 58 | 59 | #region VisitMemberExpression 60 | 61 | /// 62 | /// 解析成员访问表达式 63 | /// 64 | /// 65 | /// 66 | protected override Expression VisitMemberExpression( MemberExpression expression ) 67 | { 68 | this.VisitExpression( expression.Expression ); 69 | 70 | this.commandBuilder.OrderByParts.AppendFormat( ".{0}{1}{2}", Constants.LeftQuote, expression.Member.Name, Constants.RightQuote ); 71 | 72 | return expression; 73 | } 74 | 75 | #endregion 76 | 77 | #region CreateUnhandledItemException 78 | 79 | protected override Exception CreateUnhandledItemException( T unhandledItem, string visitMethod ) 80 | { 81 | string itemText = FormatUnhandledItem( unhandledItem ); 82 | var message = string.Format( "The expression '{0}' (type: {1}) is not supported by this LINQ provider.", itemText, typeof( T ) ); 83 | return new NotSupportedException( message ); 84 | } 85 | 86 | #endregion 87 | 88 | #region FormatUnhandledItem 89 | 90 | private string FormatUnhandledItem( T unhandledItem ) 91 | { 92 | var itemAsExpression = unhandledItem as Expression; 93 | return itemAsExpression != null ? FormattingExpressionTreeVisitor.Format( itemAsExpression ) : unhandledItem.ToString(); 94 | } 95 | 96 | #endregion 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.Oracle/CommandBuilders/OracleCommandBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Restful.Data.Oracle.Common; 3 | using System.Collections.Generic; 4 | 5 | namespace Restful.Data.Oracle.CommandBuilders 6 | { 7 | public class OracleCommandBuilder : CommandBuilder 8 | { 9 | private string sql; 10 | 11 | #region implemented abstract members of CommandBuilder 12 | 13 | public override string Sql 14 | { 15 | get 16 | { 17 | return this.sql; 18 | } 19 | set 20 | { 21 | this.sql = value; 22 | } 23 | } 24 | 25 | public override string AddParameter( object value ) 26 | { 27 | string parameterName = string.Format( "{0}P{1}", Constants.ParameterPrefix, this.parameters.Count ); 28 | 29 | this.AddParameter( parameterName, value ); 30 | 31 | return parameterName; 32 | } 33 | 34 | #endregion 35 | 36 | public OracleCommandBuilder() : base() 37 | { 38 | } 39 | 40 | public OracleCommandBuilder( string sql ) : this() 41 | { 42 | this.sql = sql; 43 | } 44 | 45 | public OracleCommandBuilder( IDictionary parameters ) : base( parameters ) 46 | { 47 | } 48 | 49 | public OracleCommandBuilder( string sql, IDictionary parameters ) : this( parameters ) 50 | { 51 | this.sql = sql; 52 | } 53 | } 54 | } 55 | 56 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.Oracle/CommandBuilders/OracleDeleteCommandBuilder.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using Restful.Data.Oracle.Common; 3 | 4 | namespace Restful.Data.Oracle.CommandBuilders 5 | { 6 | public class OracleDeleteCommandBuilder : OracleCommandBuilder 7 | { 8 | private string tableName { get; set; } 9 | 10 | public string WhereParts { get; set; } 11 | 12 | public OracleDeleteCommandBuilder( string tableName ) : base() 13 | { 14 | this.tableName = tableName; 15 | } 16 | 17 | public override string ToString() 18 | { 19 | var builder = new StringBuilder(); 20 | 21 | builder.Append( "delete from " ); 22 | builder.AppendFormat( @"{0}{1}{2} ", Constants.LeftQuote, this.tableName, Constants.RightQuote ); 23 | 24 | if( string.IsNullOrEmpty( this.WhereParts ) == false ) 25 | { 26 | builder.AppendFormat( "where {0}", this.WhereParts ); 27 | } 28 | 29 | //builder.Append( ";" ); 30 | 31 | return builder.ToString(); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.Oracle/CommandBuilders/OracleInsertCommandBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading; 4 | using System.Text; 5 | using Restful.Data.Oracle.Common; 6 | 7 | namespace Restful.Data.Oracle.CommandBuilders 8 | { 9 | public class OracleInsertCommandBuilder : OracleCommandBuilder 10 | { 11 | private string tableName { get; set; } 12 | 13 | private readonly IList columns; 14 | 15 | public OracleInsertCommandBuilder( string tableName ) : base() 16 | { 17 | this.tableName = tableName; 18 | this.columns = new List(); 19 | } 20 | 21 | public void AddColumn( string columnName, object value ) 22 | { 23 | this.AddParameter( value ); 24 | 25 | this.columns.Add( string.Format( "{0}{1}{2}", Constants.LeftQuote, columnName, Constants.RightQuote ) ); 26 | } 27 | 28 | public override string ToString() 29 | { 30 | StringBuilder builder = new StringBuilder(); 31 | 32 | builder.AppendFormat( "insert into {0}{1}{2} ", Constants.LeftQuote, this.tableName, Constants.RightQuote ); 33 | builder.AppendFormat( "( {0} ) ", string.Join( ", ", this.columns ) ); 34 | builder.AppendFormat( "values ( {0} )", string.Join( ", ", this.parameters.Keys ) ); 35 | 36 | return builder.ToString(); 37 | } 38 | } 39 | } 40 | 41 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.Oracle/CommandBuilders/OracleLimitPartsAggregator.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace Restful.Data.Oracle.CommandBuilders 3 | { 4 | internal class OracleLimitPartsAggregator 5 | { 6 | public int From { get; set; } 7 | 8 | public int Count { get; set; } 9 | 10 | public OracleLimitPartsAggregator() 11 | { 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.Oracle/CommandBuilders/OracleOrderByPartsCommandBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | 4 | namespace Restful.Data.Oracle.CommandBuilders 5 | { 6 | public class OracleOrderByPartsCommandBuilder : OracleCommandBuilder 7 | { 8 | public StringBuilder OrderByParts { get; private set; } 9 | 10 | public OracleOrderByPartsCommandBuilder() : base() 11 | { 12 | this.OrderByParts = new StringBuilder(); 13 | } 14 | 15 | public override string ToString() 16 | { 17 | return this.OrderByParts.ToString(); 18 | } 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.Oracle/CommandBuilders/OracleQueryCommandBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Restful.Data.Oracle.CommandBuilders 6 | { 7 | internal class OracleQueryCommandBuilder : OracleCommandBuilder 8 | { 9 | public bool IsDistinct { get; set; } 10 | 11 | public bool IsCount { get; set; } 12 | 13 | public string SelectPart { get; set; } 14 | 15 | public IList FromParts { get; private set; } 16 | 17 | public IList WhereParts { get; private set; } 18 | 19 | public IList OrderByParts { get; private set; } 20 | 21 | public OracleLimitPartsAggregator LimitParts { get; private set; } 22 | 23 | /// 24 | /// 25 | /// 26 | public OracleQueryCommandBuilder() : base() 27 | { 28 | this.FromParts = new List(); 29 | this.WhereParts = new List(); 30 | this.OrderByParts = new List(); 31 | this.LimitParts = new OracleLimitPartsAggregator(); 32 | } 33 | 34 | #region OnPageQuery 35 | 36 | /// 37 | /// 38 | /// 39 | private string OnPageQuery() 40 | { 41 | if( OrderByParts.Count == 0 ) 42 | throw new NotSupportedException( "必须指定排序字段。" ); 43 | 44 | var builder = new StringBuilder(); 45 | 46 | builder.Append( "select " ); 47 | 48 | if( this.IsDistinct ) 49 | { 50 | builder.Append( "distinct " ); 51 | } 52 | 53 | builder.Append( this.SelectPart ); 54 | 55 | builder.AppendFormat( " from {0} ", string.Join( ", ", this.FromParts ) ); 56 | 57 | if( this.WhereParts.Count > 0 ) 58 | { 59 | builder.AppendFormat( "where {0} ", string.Join( " and ", this.WhereParts ) ); 60 | } 61 | 62 | string orderBy = string.Empty; 63 | 64 | for( int i = 0; i < OrderByParts.Count; i++ ) 65 | { 66 | if( i == 0 ) 67 | { 68 | orderBy = orderBy + OrderByParts[i].Remove( 0, 2 ); 69 | } 70 | else 71 | { 72 | orderBy = orderBy + ", " + OrderByParts[i].Remove( 0, 2 ); 73 | } 74 | } 75 | 76 | string fields = this.IsCount ? "count(*)" : "*"; 77 | 78 | string sql = string.Format( "SELECT {0} FROM ( SELECT T.*, ROWNUM RN FROM ( {1} ) T ORDER BY {2} ) WHERE RN BETWEEN {3} AND {4}", fields, builder.ToString(), orderBy, this.LimitParts.From + 1, this.LimitParts.From + this.LimitParts.Count ); 79 | 80 | return sql; 81 | } 82 | 83 | #endregion 84 | 85 | #region OnNonPageQuery 86 | 87 | private string OnNonPageQuery() 88 | { 89 | var builder = new StringBuilder(); 90 | 91 | builder.Append( "select " ); 92 | 93 | if( this.IsDistinct ) 94 | { 95 | builder.Append( "distinct " ); 96 | } 97 | 98 | builder.Append( this.IsCount ? "count(*)" : this.SelectPart ); 99 | 100 | builder.AppendFormat( " from {0} ", string.Join( ", ", this.FromParts ) ); 101 | 102 | if( this.WhereParts.Count > 0 ) 103 | { 104 | builder.AppendFormat( "where {0} ", string.Join( " and ", this.WhereParts ) ); 105 | } 106 | 107 | if( OrderByParts.Count > 0 ) 108 | { 109 | builder.AppendFormat( "order by {0} ", string.Join( ", ", OrderByParts ) ); 110 | } 111 | 112 | return builder.ToString(); 113 | } 114 | 115 | #endregion 116 | 117 | #region ToString 118 | 119 | /// 120 | /// Returns a that represents the current . 121 | /// 122 | /// A that represents the current . 123 | 124 | public override string ToString() 125 | { 126 | // 如果是分页查询 127 | if( this.LimitParts.From != 0 || this.LimitParts.Count != 0 ) 128 | { 129 | return OnPageQuery(); 130 | } 131 | 132 | return OnNonPageQuery(); 133 | } 134 | 135 | #endregion 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.Oracle/CommandBuilders/OracleSelectPartsCommandBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | 4 | namespace Restful.Data.Oracle.CommandBuilders 5 | { 6 | public class OracleSelectPartsCommandBuilder : OracleCommandBuilder 7 | { 8 | public StringBuilder SelectPartsBuilder { get; private set; } 9 | 10 | public OracleSelectPartsCommandBuilder() : base() 11 | { 12 | this.SelectPartsBuilder = new StringBuilder(); 13 | } 14 | 15 | public override string ToString() 16 | { 17 | return this.SelectPartsBuilder.ToString(); 18 | } 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.Oracle/CommandBuilders/OracleUpdateCommandBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Restful.Data.Oracle.Common; 4 | using System.Text; 5 | 6 | namespace Restful.Data.Oracle.CommandBuilders 7 | { 8 | public class OracleUpdateCommandBuilder : OracleCommandBuilder 9 | { 10 | private string tableName { get; set; } 11 | 12 | private readonly IList columns; 13 | 14 | public string WhereParts { get; set; } 15 | 16 | public OracleUpdateCommandBuilder( string tableName ) : base() 17 | { 18 | this.tableName = tableName; 19 | this.columns = new List(); 20 | } 21 | 22 | public void AddColumn( string columnName, object value ) 23 | { 24 | string parameterName = this.AddParameter( value ); 25 | 26 | this.columns.Add( 27 | string.Format( "{0}{1}{2} = {3}", Constants.LeftQuote, columnName, Constants.RightQuote, parameterName 28 | ) ); 29 | } 30 | 31 | public override string ToString() 32 | { 33 | StringBuilder builder = new StringBuilder(); 34 | 35 | builder.AppendFormat( "update {0}{1}{2} set ", Constants.LeftQuote, this.tableName, Constants.RightQuote ); 36 | builder.AppendFormat( "{0} ", string.Join( ", ", this.columns ) ); 37 | 38 | if( string.IsNullOrEmpty( this.WhereParts ) == false ) 39 | { 40 | builder.AppendFormat( "where {0}", this.WhereParts ); 41 | } 42 | 43 | return builder.ToString(); 44 | } 45 | } 46 | } 47 | 48 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.Oracle/CommandBuilders/OracleWherePartsCommandBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Restful.Data.Oracle.Common; 4 | using System.Text; 5 | 6 | namespace Restful.Data.Oracle.CommandBuilders 7 | { 8 | public class OracleWherePartsCommandBuilder : OracleCommandBuilder 9 | { 10 | public StringBuilder WherePartsBuilder { get; private set; } 11 | 12 | public OracleWherePartsCommandBuilder() : base() 13 | { 14 | this.WherePartsBuilder = new StringBuilder(); 15 | } 16 | 17 | public OracleWherePartsCommandBuilder( IDictionary parameters ) : base( parameters ) 18 | { 19 | this.WherePartsBuilder = new StringBuilder(); 20 | } 21 | 22 | public override string ToString() 23 | { 24 | return this.WherePartsBuilder.ToString(); 25 | } 26 | } 27 | } 28 | 29 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.Oracle/Common/Constants.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Restful.Data.Oracle.Common 7 | { 8 | /// 9 | /// 定义程序集中所用的常量 10 | /// 11 | internal class Constants 12 | { 13 | /// 14 | /// 左引用符号 15 | /// 16 | public const string LeftQuote = ""; 17 | 18 | /// 19 | /// 右引用符号 20 | /// 21 | public const string RightQuote = ""; 22 | 23 | /// 24 | /// 参数前缀 25 | /// 26 | public const string ParameterPrefix = ":"; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.Oracle/Linq/OracleDeleteProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Restful.Linq; 3 | using System.Linq.Expressions; 4 | using Remotion.Linq.Parsing.ExpressionTreeVisitors; 5 | using Restful.Data.Oracle.Visitors; 6 | using Restful.Data.Oracle.CommandBuilders; 7 | 8 | namespace Restful.Data.Oracle.Linq 9 | { 10 | public class OracleDeleteProvider : IDeleteProvider 11 | { 12 | private readonly ISessionProvider sessionProvider; 13 | 14 | public OracleDeleteProvider( ISessionProvider sessionProvider ) 15 | { 16 | this.sessionProvider = sessionProvider; 17 | } 18 | 19 | #region IDeleteProvider implementation 20 | 21 | public IDeleteable CreateDelete( Type elementType ) 22 | { 23 | return (IDeleteable)Activator.CreateInstance( typeof( OracleDeleteable<> ).MakeGenericType( elementType ), new object[] { this, elementType } ); 24 | } 25 | 26 | public int Execute( Type elementType, Expression predicate ) 27 | { 28 | OracleDeleteCommandBuilder deleteBuilder = new OracleDeleteCommandBuilder( elementType.Name ); 29 | 30 | if( predicate != null ) 31 | { 32 | OracleWherePartsCommandBuilder whereBuilder = new OracleWherePartsCommandBuilder( deleteBuilder.Parameters ); 33 | 34 | Expression expression = PartialEvaluatingExpressionTreeVisitor.EvaluateIndependentSubtrees( predicate ); 35 | 36 | OracleWhereClauseVisitor visitor = new OracleWhereClauseVisitor(); 37 | 38 | visitor.Translate( expression, whereBuilder ); 39 | 40 | deleteBuilder.WhereParts = whereBuilder.WherePartsBuilder.ToString(); 41 | } 42 | 43 | this.sessionProvider.ExecutedCommandBuilder = deleteBuilder; 44 | 45 | return this.sessionProvider.ExecuteNonQuery( deleteBuilder ); 46 | } 47 | 48 | public IDeleteable CreateDelete() 49 | { 50 | return new OracleDeleteable( this ); 51 | } 52 | 53 | public int Execute( Expression predicate ) 54 | { 55 | return Execute( typeof( T ), predicate ); 56 | } 57 | 58 | #endregion 59 | } 60 | } 61 | 62 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.Oracle/Linq/OracleDeleteable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq.Expressions; 4 | using Remotion.Linq.Parsing.ExpressionTreeVisitors; 5 | using Restful.Linq; 6 | using Restful.Data.Oracle.CommandBuilders; 7 | using Restful.Data.Oracle.Visitors; 8 | 9 | namespace Restful.Data.Oracle.Linq 10 | { 11 | public class OracleDeleteable : IDeleteable 12 | { 13 | private readonly Type elementType; 14 | private readonly IDeleteProvider provider; 15 | 16 | public OracleDeleteable( IDeleteProvider provider ) 17 | { 18 | this.provider = provider; 19 | this.elementType = typeof( T ); 20 | } 21 | 22 | public OracleDeleteable( IDeleteProvider provider, Type elementType ) 23 | { 24 | this.provider = provider; 25 | this.elementType = elementType; 26 | } 27 | 28 | #region IDeleteable implementation 29 | 30 | public Type ElementType 31 | { 32 | get 33 | { 34 | return this.elementType; 35 | } 36 | } 37 | 38 | public Expression Predicate { get; set; } 39 | 40 | public IDeleteProvider Provider 41 | { 42 | get 43 | { 44 | return this.provider; 45 | } 46 | } 47 | 48 | #endregion 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.Oracle/Linq/OracleInsertProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Linq.Expressions; 5 | using System.Text; 6 | using Remotion.Linq.Parsing.ExpressionTreeVisitors; 7 | using Restful.Linq; 8 | using Restful.Data.Oracle.CommandBuilders; 9 | using Restful.Data.Oracle.Common; 10 | using Restful.Data.Oracle.Visitors; 11 | 12 | namespace Restful.Data.Oracle.Linq 13 | { 14 | public class OracleInsertProvider : IInsertProvider 15 | { 16 | private readonly ISessionProvider sessionProvider; 17 | 18 | public OracleInsertProvider( ISessionProvider sessionProvider ) 19 | { 20 | this.sessionProvider = sessionProvider; 21 | } 22 | 23 | public IInsertable CreateInsert( Type elementType ) 24 | { 25 | return (IInsertable)Activator.CreateInstance( typeof( OracleInsertable<> ).MakeGenericType( elementType ), new object[] { this, elementType } ); 26 | } 27 | 28 | public int Execute( Type elementType, IDictionary properties ) 29 | { 30 | OracleInsertCommandBuilder insertBuilder = new OracleInsertCommandBuilder( elementType.Name ); 31 | 32 | foreach( var item in properties ) 33 | { 34 | insertBuilder.AddColumn( item.Key.Member.Name, item.Value ); 35 | } 36 | 37 | this.sessionProvider.ExecutedCommandBuilder = insertBuilder; 38 | 39 | return this.sessionProvider.ExecuteNonQuery( insertBuilder ); 40 | } 41 | 42 | public IInsertable CreateInsert() 43 | { 44 | return new OracleInsertable( this ); 45 | } 46 | 47 | public int Execute( IDictionary properties ) 48 | { 49 | return this.Execute( typeof( T ), properties ); 50 | } 51 | } 52 | } 53 | 54 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.Oracle/Linq/OracleInsetable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | using Remotion.Linq.Parsing.ExpressionTreeVisitors; 4 | using Restful.Data.Oracle.CommandBuilders; 5 | using Restful.Data.Oracle.Visitors; 6 | using System.Collections.Generic; 7 | using Restful.Linq; 8 | 9 | namespace Restful.Data.Oracle.Linq 10 | { 11 | public class OracleInsertable : IInsertable 12 | { 13 | private readonly Type elementType; 14 | private readonly IDictionary properties; 15 | private readonly IInsertProvider provider; 16 | 17 | public OracleInsertable( IInsertProvider provider ) 18 | { 19 | this.provider = provider; 20 | this.elementType = typeof( T ); 21 | this.properties = new Dictionary(); 22 | } 23 | 24 | public OracleInsertable( IInsertProvider provider, Type elementType ) 25 | { 26 | this.provider = provider; 27 | this.elementType = elementType; 28 | this.properties = new Dictionary(); 29 | } 30 | 31 | #region IInsertable implementation 32 | 33 | public Type ElementType 34 | { 35 | get 36 | { 37 | return this.elementType; 38 | } 39 | } 40 | 41 | public IDictionary Properties 42 | { 43 | get 44 | { 45 | return this.properties; 46 | } 47 | } 48 | 49 | 50 | public IInsertProvider Provider 51 | { 52 | get 53 | { 54 | return this.provider; 55 | } 56 | } 57 | 58 | #endregion 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.Oracle/Linq/OracleQueryExecutor.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Data; 3 | using System.Data.Common; 4 | using Remotion.Linq; 5 | using Restful.Data.Oracle.Visitors; 6 | using System; 7 | 8 | namespace Restful.Data.Oracle.Linq 9 | { 10 | public class OracleQueryExecutor : IQueryExecutor 11 | { 12 | protected ISessionProvider provider; 13 | 14 | public OracleQueryExecutor( ISessionProvider provider ) 15 | { 16 | this.provider = provider; 17 | } 18 | 19 | #region ExecuteCollection 20 | 21 | /// 22 | /// 执行查询,并返回 IEnumerable 对象 23 | /// 24 | /// 25 | /// 26 | /// 27 | public IEnumerable ExecuteCollection( QueryModel queryModel ) 28 | { 29 | OracleQueryModelVisitor queryModelVisitor = new OracleQueryModelVisitor(); 30 | 31 | var command = queryModelVisitor.Translate( queryModel ); 32 | 33 | this.provider.ExecutedCommandBuilder = command; 34 | 35 | using( IDataReader reader = this.provider.ExecuteDataReader( command ) ) 36 | { 37 | var tuple = reader.GetDeserializerState(); 38 | 39 | while( reader.Read() ) 40 | { 41 | yield return (T)tuple.Func( reader ); 42 | } 43 | } 44 | } 45 | 46 | #endregion 47 | 48 | #region ExecuteScalar 49 | 50 | /// 51 | /// 执行查询,并返回第一行第一列 52 | /// 53 | /// 54 | /// 55 | /// 56 | public T ExecuteScalar( QueryModel queryModel ) 57 | { 58 | OracleQueryModelVisitor queryModelVisitor = new OracleQueryModelVisitor(); 59 | 60 | var command = queryModelVisitor.Translate( queryModel ); 61 | 62 | this.provider.ExecutedCommandBuilder = command; 63 | 64 | return this.provider.ExecuteScalar( command ); 65 | } 66 | 67 | #endregion 68 | 69 | #region ExecuteSingle 70 | 71 | /// 72 | /// 执行查询,并返回单个对象 73 | /// 74 | /// 75 | /// 76 | /// 77 | /// 78 | public T ExecuteSingle( QueryModel queryModel, bool returnDefaultWhenEmpty ) 79 | { 80 | OracleQueryModelVisitor queryModelVisitor = new OracleQueryModelVisitor(); 81 | 82 | var command = queryModelVisitor.Translate( queryModel ); 83 | 84 | this.provider.ExecutedCommandBuilder = command; 85 | 86 | using( IDataReader reader = this.provider.ExecuteDataReader( command ) ) 87 | { 88 | bool isExists = reader.Read(); 89 | 90 | // 如果不存在查询记录 91 | if( isExists == false ) 92 | { 93 | // 如果可以默认 94 | if( returnDefaultWhenEmpty ) 95 | { 96 | return default( T ); 97 | } 98 | else 99 | { 100 | throw new InvalidOperationException( "未查询出满足条件的任何记录。" ); 101 | } 102 | } 103 | 104 | var tuple = reader.GetDeserializerState(); 105 | 106 | return (T)tuple.Func( reader ); 107 | } 108 | } 109 | 110 | #endregion 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.Oracle/Linq/OracleQueryable.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Linq.Expressions; 3 | using Remotion.Linq; 4 | using Remotion.Linq.Parsing.Structure; 5 | 6 | namespace Restful.Data.Oracle.Linq 7 | { 8 | public class OracleQueryable : QueryableBase 9 | { 10 | public OracleQueryable( IQueryParser queryParser, IQueryExecutor executor ) 11 | : base( new DefaultQueryProvider( typeof( OracleQueryable<> ), queryParser, executor ) ) 12 | { 13 | } 14 | 15 | public OracleQueryable( IQueryProvider provider, Expression expression ) 16 | : base( provider, expression ) 17 | { 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.Oracle/Linq/OracleUpdateProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Restful.Linq; 3 | using System.Linq.Expressions; 4 | using Remotion.Linq.Parsing.ExpressionTreeVisitors; 5 | using Restful.Data.Oracle.Visitors; 6 | using Restful.Data.Oracle.CommandBuilders; 7 | using System.Collections.Generic; 8 | using System.Text; 9 | using System.Collections; 10 | using Restful.Data.Oracle.Common; 11 | 12 | namespace Restful.Data.Oracle.Linq 13 | { 14 | public class OracleUpdateProvider : IUpdateProvider 15 | { 16 | private readonly ISessionProvider sessionProvider; 17 | 18 | public OracleUpdateProvider( ISessionProvider sessionProvider ) 19 | { 20 | this.sessionProvider = sessionProvider; 21 | } 22 | 23 | public IUpdateable CreateUpdate( Type elementType ) 24 | { 25 | return (IUpdateable)Activator.CreateInstance( typeof( OracleUpdateable<> ).MakeGenericType( elementType ), new object[] { this, elementType } ); 26 | } 27 | 28 | public IUpdateable CreateUpdate() 29 | { 30 | return new OracleUpdateable( this ); 31 | } 32 | 33 | public int Execute( Type elementType, IDictionary properties, Expression predicate ) 34 | { 35 | OracleUpdateCommandBuilder updateBuilder = new OracleUpdateCommandBuilder( elementType.Name ); 36 | 37 | foreach( var item in properties ) 38 | { 39 | updateBuilder.AddColumn( item.Key.Member.Name, item.Value ); 40 | } 41 | 42 | if( predicate != null ) 43 | { 44 | OracleWherePartsCommandBuilder whereBuider = new OracleWherePartsCommandBuilder( updateBuilder.Parameters ); 45 | 46 | Expression expression = PartialEvaluatingExpressionTreeVisitor.EvaluateIndependentSubtrees( predicate ); 47 | 48 | OracleWhereClauseVisitor visitor = new OracleWhereClauseVisitor(); 49 | 50 | visitor.Translate( expression, whereBuider ); 51 | 52 | updateBuilder.WhereParts = whereBuider.WherePartsBuilder.ToString(); 53 | } 54 | 55 | this.sessionProvider.ExecutedCommandBuilder = updateBuilder; 56 | 57 | return this.sessionProvider.ExecuteNonQuery( updateBuilder ); 58 | } 59 | 60 | public int Execute( IDictionary properties, Expression predicate ) 61 | { 62 | return this.Execute( typeof( T ), properties, predicate ); 63 | } 64 | 65 | } 66 | } 67 | 68 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.Oracle/OracleSession.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Restful.Data.Oracle 7 | { 8 | public class OracleSession : ISession 9 | { 10 | private OracleSessionProvider provider; 11 | 12 | public OracleSession( ISessionProviderFactory factory, string connectionStr ) 13 | { 14 | this.provider = new OracleSessionProvider( factory, connectionStr ); 15 | } 16 | 17 | public int CommandTimeout 18 | { 19 | get 20 | { 21 | return this.provider.CommandTimeout; 22 | } 23 | set 24 | { 25 | this.provider.CommandTimeout = value; 26 | } 27 | } 28 | 29 | public ISessionProvider Provider 30 | { 31 | get { return this.provider; } 32 | } 33 | 34 | public void Dispose() 35 | { 36 | this.provider.Dispose(); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.Oracle/OracleSessionProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Data; 4 | using System.Data.Common; 5 | using System.Diagnostics; 6 | using System.Linq; 7 | using System.Reflection; 8 | using System.Text; 9 | using Remotion.Linq.Parsing.Structure; 10 | using Restful; 11 | using Restful.Data.Attributes; 12 | using Restful.Data.Oracle.Common; 13 | using Restful.Data.Oracle.Linq; 14 | 15 | namespace Restful.Data.Oracle 16 | { 17 | public class OracleSessionProvider : SessionProvider 18 | { 19 | #region OracleSessionProvider 20 | 21 | /// 22 | /// 构造函数 23 | /// 24 | /// 25 | public OracleSessionProvider( ISessionProviderFactory factory, string connectionStr ) : base( factory, connectionStr ) 26 | { 27 | 28 | } 29 | 30 | #endregion 31 | 32 | #region ExecuteDataPage 33 | 34 | /// 35 | /// 执行分页查询 36 | /// 37 | /// SQL 语句 38 | /// 页索引 39 | /// 页大小 40 | /// 排序字段 41 | /// 参数列表 42 | /// 分页查询结果 43 | public override DataPage ExecuteDataPage( CommandBuilder command, int pageIndex, int pageSize, string orderBy ) 44 | { 45 | if( string.IsNullOrEmpty( orderBy ) ) 46 | { 47 | throw new ArgumentNullException( "orderBy" ); 48 | } 49 | 50 | DataPage dataPage = new DataPage( pageIndex, pageSize ); 51 | 52 | #region 查询满足条件的条目数量 53 | string queryItemCountSql = string.Format( "SELECT COUNT(*) FROM ( {0} ) T1", command.ToString() ); 54 | 55 | dataPage.ItemCount = this.ExecuteScalar( new Restful.Data.Oracle.CommandBuilders.OracleCommandBuilder( queryItemCountSql, command.Parameters ) ); 56 | 57 | if( dataPage.ItemCount == 0 ) // 如果满足条件的数据条目数量为零,则重置页索引为 1 58 | { 59 | dataPage.PageIndex = 1; 60 | } 61 | else if( dataPage.PageIndex > dataPage.PageCount ) // 如果指定的页索引大于查询直接总页数,则重置页索引为总页数 62 | { 63 | dataPage.PageIndex = dataPage.PageCount; 64 | } 65 | #endregion 66 | 67 | #region 查询最终的结果集 68 | 69 | string limitFrom = string.Format( "{0}LimitFrom", Constants.ParameterPrefix ); 70 | string limitTo = string.Format( "{0}LimitTo", Constants.ParameterPrefix ); 71 | 72 | command.Parameters.Add( limitFrom, ( dataPage.PageIndex - 1 ) * dataPage.PageSize + 1 ); 73 | command.Parameters.Add( limitTo, dataPage.PageIndex * dataPage.PageSize ); 74 | 75 | string queryItemSql = string.Format( "SELECT * FROM ( SELECT T.*, ROWNUM RN FROM ( {0} ) T ORDER BY {1} ) WHERE RN BETWEEN {2} AND {3}", command.ToString(), orderBy, limitFrom, limitTo ); 76 | 77 | dataPage.Data = this.ExecuteDataTable( new Restful.Data.Oracle.CommandBuilders.OracleCommandBuilder( queryItemSql, command.Parameters ) ); 78 | #endregion 79 | 80 | return dataPage; 81 | } 82 | 83 | #endregion 84 | 85 | #region GetIdentifier 86 | 87 | /// 88 | /// 获取最新插入数据的自增ID 89 | /// 90 | /// 91 | /// 92 | public override T GetIdentifier() 93 | { 94 | throw new NotSupportedException( "Oracle 不支持。" ); 95 | } 96 | 97 | #endregion 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.Oracle/OracleSessionProviderFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Data; 6 | using System.Data.Common; 7 | using Restful.Data.Oracle.Linq; 8 | using Remotion.Linq.Parsing.Structure; 9 | using Remotion.Linq; 10 | using Restful.Data.Oracle.CommandBuilders; 11 | using Restful.Data.Oracle.Visitors; 12 | using Restful.Linq; 13 | using Oracle.DataAccess.Client; 14 | 15 | namespace Restful.Data.Oracle 16 | { 17 | public class OracleSessionProviderFactory : ISessionProviderFactory 18 | { 19 | public CommandBuilder CreateCommandBuilder() 20 | { 21 | return new Restful.Data.Oracle.CommandBuilders.OracleCommandBuilder(); 22 | } 23 | 24 | public IUpdateProvider CreateUpdateProvider( ISessionProvider provider ) 25 | { 26 | return new OracleUpdateProvider( provider ); 27 | } 28 | 29 | public IInsertProvider CreateInsertProvider( ISessionProvider provider ) 30 | { 31 | return new OracleInsertProvider( provider ); 32 | } 33 | 34 | public IDeleteProvider CreateDeleteProvider( ISessionProvider provider ) 35 | { 36 | return new OracleDeleteProvider( provider ); 37 | } 38 | 39 | public ISession CreateSession( string connectionStr ) 40 | { 41 | return new OracleSession( this, connectionStr ); 42 | } 43 | 44 | public DbConnection CreateConnection( string connectionStr ) 45 | { 46 | return new OracleConnection( connectionStr ); 47 | } 48 | 49 | public DbDataAdapter CreateDataAdapter() 50 | { 51 | return new OracleDataAdapter(); 52 | } 53 | 54 | public IQueryable CreateQueryable( ISessionProvider provider ) 55 | { 56 | return new OracleQueryable( QueryParser.CreateDefault(), new OracleQueryExecutor( provider ) ); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.Oracle/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | 4 | // Information about this assembly is defined by the following attributes. 5 | // Change them to the values specific to your project. 6 | 7 | [assembly: AssemblyTitle( "Restful.Data.Oracle" )] 8 | [assembly: AssemblyDescription( "" )] 9 | [assembly: AssemblyConfiguration( "" )] 10 | [assembly: AssemblyCompany( "" )] 11 | [assembly: AssemblyProduct( "" )] 12 | [assembly: AssemblyCopyright( "zhaogh" )] 13 | [assembly: AssemblyTrademark( "" )] 14 | [assembly: AssemblyCulture( "" )] 15 | 16 | // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". 17 | // The form "{Major}.{Minor}.*" will automatically update the build and revision, 18 | // and "{Major}.{Minor}.{Build}.*" will update just the revision. 19 | 20 | [assembly: AssemblyVersion( "1.0.*" )] 21 | 22 | // The following attributes are used to specify the signing key for the assembly, 23 | // if desired. See the Mono documentation for more information about signing. 24 | 25 | //[assembly: AssemblyDelaySign(false)] 26 | //[assembly: AssemblyKeyFile("")] 27 | 28 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.Oracle/Restful.Data.Oracle.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | {D42F1E6A-CD91-49CE-B3D0-95906C62C471} 7 | Library 8 | Restful.Data.Oracle 9 | Restful.Data.Oracle 10 | 2.0 11 | 12 | 13 | true 14 | full 15 | false 16 | ..\..\..\lib 17 | DEBUG; 18 | prompt 19 | 4 20 | false 21 | 22 | 23 | full 24 | true 25 | ..\..\..\lib 26 | prompt 27 | 4 28 | false 29 | AnyCPU 30 | 31 | 32 | 33 | False 34 | ..\References\Oracle.DataAccess.dll 35 | 36 | 37 | 38 | ..\References\Remotion.Linq.dll 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | {39D214BE-3A4A-4174-8C53-5B7B5654D1AA} 76 | Restful.Linq 77 | 78 | 79 | {4BA05EF7-5312-4B37-B0A2-07E68DD05BEA} 80 | Restful.Data 81 | 82 | 83 | {ECEDCBF3-7039-4A01-B87A-DA84DA939404} 84 | Restful 85 | 86 | 87 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.Oracle/Visitors/OracleOrderByClauseVisitor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq.Expressions; 4 | using System.Text; 5 | using Remotion.Linq.Clauses.ExpressionTreeVisitors; 6 | using Remotion.Linq.Clauses.Expressions; 7 | using Remotion.Linq.Parsing; 8 | using Restful.Data.Oracle.Common; 9 | using Restful.Data.Oracle.CommandBuilders; 10 | 11 | namespace Restful.Data.Oracle.Visitors 12 | { 13 | internal class OracleOrderByClauseVisitor : ThrowingExpressionTreeVisitor 14 | { 15 | private OracleOrderByPartsCommandBuilder commandBuilder; 16 | 17 | #region OrderByClauseVisitor 18 | 19 | /// 20 | /// 构造函数 21 | /// 22 | public OracleOrderByClauseVisitor() 23 | { 24 | } 25 | 26 | #endregion 27 | 28 | #region Translate 29 | 30 | /// 31 | /// 翻译表达式 32 | /// 33 | /// 34 | public void Translate( Expression expression, OracleOrderByPartsCommandBuilder commandBuilder ) 35 | { 36 | this.commandBuilder = commandBuilder; 37 | 38 | this.VisitExpression( expression ); 39 | } 40 | 41 | #endregion 42 | 43 | #region VisitQuerySourceReferenceExpression 44 | 45 | /// 46 | /// 解析查询源引用表达式 47 | /// 48 | /// 49 | /// 50 | protected override Expression VisitQuerySourceReferenceExpression( QuerySourceReferenceExpression expression ) 51 | { 52 | this.commandBuilder.OrderByParts.Append( expression.ReferencedQuerySource.ItemName.ToLower() ); 53 | 54 | return expression; 55 | } 56 | 57 | #endregion 58 | 59 | #region VisitMemberExpression 60 | 61 | /// 62 | /// 解析成员访问表达式 63 | /// 64 | /// 65 | /// 66 | protected override Expression VisitMemberExpression( MemberExpression expression ) 67 | { 68 | this.VisitExpression( expression.Expression ); 69 | 70 | this.commandBuilder.OrderByParts.AppendFormat( ".{0}{1}{2}", Constants.LeftQuote, expression.Member.Name, Constants.RightQuote ); 71 | 72 | return expression; 73 | } 74 | 75 | #endregion 76 | 77 | #region CreateUnhandledItemException 78 | 79 | protected override Exception CreateUnhandledItemException( T unhandledItem, string visitMethod ) 80 | { 81 | string itemText = FormatUnhandledItem( unhandledItem ); 82 | var message = string.Format( "The expression '{0}' (type: {1}) is not supported by this LINQ provider.", itemText, typeof( T ) ); 83 | return new NotSupportedException( message ); 84 | } 85 | 86 | #endregion 87 | 88 | #region FormatUnhandledItem 89 | 90 | private string FormatUnhandledItem( T unhandledItem ) 91 | { 92 | var itemAsExpression = unhandledItem as Expression; 93 | return itemAsExpression != null ? FormattingExpressionTreeVisitor.Format( itemAsExpression ) : unhandledItem.ToString(); 94 | } 95 | 96 | #endregion 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.SqlServer/CommandBuilders/SqlServerCommandBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Restful.Data.SqlServer.Common; 3 | using System.Collections.Generic; 4 | 5 | namespace Restful.Data.SqlServer.CommandBuilders 6 | { 7 | public class SqlServerCommandBuilder : CommandBuilder 8 | { 9 | private string sql; 10 | 11 | #region implemented abstract members of CommandBuilder 12 | 13 | public override string Sql 14 | { 15 | get 16 | { 17 | return this.sql; 18 | } 19 | set 20 | { 21 | this.sql = value; 22 | } 23 | } 24 | 25 | public override string AddParameter( object value ) 26 | { 27 | string parameterName = string.Format( "{0}P{1}", Constants.ParameterPrefix, this.parameters.Count ); 28 | 29 | this.AddParameter( parameterName, value ); 30 | 31 | return parameterName; 32 | } 33 | 34 | #endregion 35 | 36 | public SqlServerCommandBuilder() : base() 37 | { 38 | } 39 | 40 | public SqlServerCommandBuilder( string sql ) : this() 41 | { 42 | this.sql = sql; 43 | } 44 | 45 | public SqlServerCommandBuilder( IDictionary parameters ) : base( parameters ) 46 | { 47 | } 48 | 49 | public SqlServerCommandBuilder( string sql, IDictionary parameters ) : this( parameters ) 50 | { 51 | this.sql = sql; 52 | } 53 | } 54 | } 55 | 56 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.SqlServer/CommandBuilders/SqlServerDeleteCommandBuilder.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using Restful.Data.SqlServer.Common; 3 | 4 | namespace Restful.Data.SqlServer.CommandBuilders 5 | { 6 | public class SqlServerDeleteCommandBuilder : SqlServerCommandBuilder 7 | { 8 | private string tableName { get; set; } 9 | 10 | public string WhereParts { get; set; } 11 | 12 | public SqlServerDeleteCommandBuilder( string tableName ) : base() 13 | { 14 | this.tableName = tableName; 15 | } 16 | 17 | public override string ToString() 18 | { 19 | var builder = new StringBuilder(); 20 | 21 | builder.Append( "delete from " ); 22 | builder.AppendFormat( "{0}{1}{2} ", Constants.LeftQuote, this.tableName, Constants.RightQuote ); 23 | 24 | if( string.IsNullOrEmpty( this.WhereParts ) == false ) 25 | { 26 | builder.AppendFormat( "where {0}", this.WhereParts ); 27 | } 28 | 29 | builder.Append( ";" ); 30 | 31 | return builder.ToString(); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.SqlServer/CommandBuilders/SqlServerInsertCommandBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading; 4 | using System.Text; 5 | using Restful.Data.SqlServer.Common; 6 | 7 | namespace Restful.Data.SqlServer.CommandBuilders 8 | { 9 | public class SqlServerInsertCommandBuilder : SqlServerCommandBuilder 10 | { 11 | private string tableName { get; set; } 12 | 13 | private readonly IList columns; 14 | 15 | public SqlServerInsertCommandBuilder( string tableName ) : base() 16 | { 17 | this.tableName = tableName; 18 | this.columns = new List(); 19 | } 20 | 21 | public void AddColumn( string columnName, object value ) 22 | { 23 | this.AddParameter( value ); 24 | 25 | this.columns.Add( string.Format( "{0}{1}{2}", Constants.LeftQuote, columnName, Constants.RightQuote ) ); 26 | } 27 | 28 | public override string ToString() 29 | { 30 | StringBuilder builder = new StringBuilder(); 31 | 32 | builder.AppendFormat( "insert into {0}{1}{2} ", Constants.LeftQuote, this.tableName, Constants.RightQuote ); 33 | builder.AppendFormat( "( {0} ) ", string.Join( ", ", this.columns ) ); 34 | builder.AppendFormat( "values ( {0} );", string.Join( ", ", this.parameters.Keys ) ); 35 | 36 | return builder.ToString(); 37 | } 38 | } 39 | } 40 | 41 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.SqlServer/CommandBuilders/SqlServerLimitPartsAggregator.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace Restful.Data.SqlServer.CommandBuilders 3 | { 4 | internal class SqlServerLimitPartsAggregator 5 | { 6 | public int From { get; set; } 7 | 8 | public int Count { get; set; } 9 | 10 | public SqlServerLimitPartsAggregator() 11 | { 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.SqlServer/CommandBuilders/SqlServerOrderByPartsCommandBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | 4 | namespace Restful.Data.SqlServer.CommandBuilders 5 | { 6 | public class SqlServerOrderByPartsCommandBuilder : SqlServerCommandBuilder 7 | { 8 | public StringBuilder OrderByParts { get; private set; } 9 | 10 | public SqlServerOrderByPartsCommandBuilder() : base() 11 | { 12 | this.OrderByParts = new StringBuilder(); 13 | } 14 | 15 | public override string ToString() 16 | { 17 | return this.OrderByParts.ToString(); 18 | } 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.SqlServer/CommandBuilders/SqlServerQueryCommandBuilder.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Text; 3 | using System; 4 | 5 | namespace Restful.Data.SqlServer.CommandBuilders 6 | { 7 | internal class SqlServerQueryCommandBuilder : SqlServerCommandBuilder 8 | { 9 | public bool IsDistinct { get; set; } 10 | 11 | public bool IsCount { get; set; } 12 | 13 | public string SelectPart { get; set; } 14 | 15 | public IList FromParts { get; private set; } 16 | 17 | public IList WhereParts { get; private set; } 18 | 19 | public IList OrderByParts { get; private set; } 20 | 21 | public SqlServerLimitPartsAggregator LimitParts { get; private set; } 22 | 23 | /// 24 | /// 25 | /// 26 | public SqlServerQueryCommandBuilder() : base() 27 | { 28 | this.FromParts = new List(); 29 | this.WhereParts = new List(); 30 | this.OrderByParts = new List(); 31 | this.LimitParts = new SqlServerLimitPartsAggregator(); 32 | } 33 | 34 | #region OnPageQuery 35 | 36 | /// 37 | /// 38 | /// 39 | private string OnPageQuery() 40 | { 41 | if( OrderByParts.Count == 0 ) 42 | throw new NotSupportedException( "在 SQL Server 中进行分页查询,必须指定排序字段。" ); 43 | 44 | var builder = new StringBuilder(); 45 | 46 | builder.Append( "select " ); 47 | 48 | if( this.IsDistinct ) 49 | { 50 | builder.Append( "distinct " ); 51 | } 52 | 53 | builder.Append( this.SelectPart ); 54 | 55 | builder.AppendFormat( " from {0} ", string.Join( ", ", this.FromParts ) ); 56 | 57 | if( this.WhereParts.Count > 0 ) 58 | { 59 | builder.AppendFormat( "where {0} ", string.Join( " and ", this.WhereParts ) ); 60 | } 61 | 62 | string orderBy = string.Empty; 63 | 64 | for( int i = 0; i < OrderByParts.Count; i++ ) 65 | { 66 | if( i == 0 ) 67 | { 68 | orderBy = orderBy + OrderByParts[i].Remove( 0, 2 ); 69 | } 70 | else 71 | { 72 | orderBy = orderBy + ", " + OrderByParts[i].Remove( 0, 2 ); 73 | } 74 | } 75 | 76 | string fields = this.IsCount ? "count(*)" : "*"; 77 | 78 | string sql = string.Format( "select {0} from ( select *, row_number() over( order by {1} ) as RowNumber from ( {2} ) a ) t where RowNumber between {3} and {4} ", fields, orderBy, builder.ToString(), this.LimitParts.From + 1, this.LimitParts.From + this.LimitParts.Count ); 79 | 80 | return sql; 81 | } 82 | 83 | #endregion 84 | 85 | #region OnNonPageQuery 86 | 87 | private string OnNonPageQuery() 88 | { 89 | var builder = new StringBuilder(); 90 | 91 | builder.Append( "select " ); 92 | 93 | if( this.IsDistinct ) 94 | { 95 | builder.Append( "distinct " ); 96 | } 97 | 98 | builder.Append( this.IsCount ? "count(*)" : this.SelectPart ); 99 | 100 | builder.AppendFormat( " from {0} ", string.Join( ", ", this.FromParts ) ); 101 | 102 | if( this.WhereParts.Count > 0 ) 103 | { 104 | builder.AppendFormat( "where {0} ", string.Join( " and ", this.WhereParts ) ); 105 | } 106 | 107 | if( OrderByParts.Count > 0 ) 108 | { 109 | builder.AppendFormat( "order by {0} ", string.Join( ", ", OrderByParts ) ); 110 | } 111 | 112 | return builder.ToString(); 113 | } 114 | 115 | #endregion 116 | 117 | #region ToString 118 | 119 | /// 120 | /// Returns a that represents the current . 121 | /// 122 | /// A that represents the current . 123 | 124 | public override string ToString() 125 | { 126 | // 如果是分页查询 127 | if( this.LimitParts.From != 0 || this.LimitParts.Count != 0 ) 128 | { 129 | return OnPageQuery(); 130 | } 131 | 132 | return OnNonPageQuery(); 133 | } 134 | 135 | #endregion 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.SqlServer/CommandBuilders/SqlServerSelectPartsCommandBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | 4 | namespace Restful.Data.SqlServer.CommandBuilders 5 | { 6 | public class SqlServerSelectPartsCommandBuilder : SqlServerCommandBuilder 7 | { 8 | public StringBuilder SelectPartsBuilder { get; private set; } 9 | 10 | public SqlServerSelectPartsCommandBuilder() : base() 11 | { 12 | this.SelectPartsBuilder = new StringBuilder(); 13 | } 14 | 15 | public override string ToString() 16 | { 17 | return this.SelectPartsBuilder.ToString(); 18 | } 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.SqlServer/CommandBuilders/SqlServerUpdateCommandBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Restful.Data.SqlServer.Common; 4 | using System.Text; 5 | 6 | namespace Restful.Data.SqlServer.CommandBuilders 7 | { 8 | public class SqlServerUpdateCommandBuilder : SqlServerCommandBuilder 9 | { 10 | private string tableName { get; set; } 11 | 12 | private readonly IList columns; 13 | 14 | public string WhereParts { get; set; } 15 | 16 | public SqlServerUpdateCommandBuilder( string tableName ) : base() 17 | { 18 | this.tableName = tableName; 19 | this.columns = new List(); 20 | } 21 | 22 | public void AddColumn( string columnName, object value ) 23 | { 24 | string parameterName = this.AddParameter( value ); 25 | 26 | this.columns.Add( 27 | string.Format( "{0}{1}{2} = {3}", Constants.LeftQuote, columnName, Constants.RightQuote, parameterName 28 | ) ); 29 | } 30 | 31 | public override string ToString() 32 | { 33 | StringBuilder builder = new StringBuilder(); 34 | 35 | builder.AppendFormat( "update {0}{1}{2} set ", Constants.LeftQuote, this.tableName, Constants.RightQuote ); 36 | builder.AppendFormat( "{0} ", string.Join( ", ", this.columns ) ); 37 | 38 | if( string.IsNullOrEmpty( this.WhereParts ) == false ) 39 | { 40 | builder.AppendFormat( "where {0};", this.WhereParts ); 41 | } 42 | 43 | return builder.ToString(); 44 | } 45 | } 46 | } 47 | 48 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.SqlServer/CommandBuilders/SqlServerWherePartsCommandBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Restful.Data.SqlServer.Common; 4 | using System.Text; 5 | 6 | namespace Restful.Data.SqlServer.CommandBuilders 7 | { 8 | public class SqlServerWherePartsCommandBuilder : SqlServerCommandBuilder 9 | { 10 | public StringBuilder WherePartsBuilder { get; private set; } 11 | 12 | public SqlServerWherePartsCommandBuilder() : base() 13 | { 14 | this.WherePartsBuilder = new StringBuilder(); 15 | } 16 | 17 | public SqlServerWherePartsCommandBuilder( IDictionary parameters ) : base( parameters ) 18 | { 19 | this.WherePartsBuilder = new StringBuilder(); 20 | } 21 | 22 | public override string ToString() 23 | { 24 | return this.WherePartsBuilder.ToString(); 25 | } 26 | } 27 | } 28 | 29 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.SqlServer/Common/Constants.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Restful.Data.SqlServer.Common 7 | { 8 | /// 9 | /// 定义程序集中所用的常量 10 | /// 11 | internal class Constants 12 | { 13 | /// 14 | /// 左引用符号 15 | /// 16 | public const string LeftQuote = "["; 17 | 18 | /// 19 | /// 右引用符号 20 | /// 21 | public const string RightQuote = "]"; 22 | 23 | /// 24 | /// 参数前缀 25 | /// 26 | public const string ParameterPrefix = "@"; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.SqlServer/Linq/SqlServerDeleteProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Restful.Linq; 3 | using System.Linq.Expressions; 4 | using Remotion.Linq.Parsing.ExpressionTreeVisitors; 5 | using Restful.Data.SqlServer.Visitors; 6 | using Restful.Data.SqlServer.CommandBuilders; 7 | 8 | namespace Restful.Data.SqlServer.Linq 9 | { 10 | public class SqlServerDeleteProvider : IDeleteProvider 11 | { 12 | private readonly ISessionProvider sessionProvider; 13 | 14 | public SqlServerDeleteProvider( ISessionProvider sessionProvider ) 15 | { 16 | this.sessionProvider = sessionProvider; 17 | } 18 | 19 | #region IDeleteProvider implementation 20 | 21 | public IDeleteable CreateDelete( Type elementType ) 22 | { 23 | return (IDeleteable)Activator.CreateInstance( typeof( SqlServerDeleteable<> ).MakeGenericType( elementType ), new object[] { this, elementType } ); 24 | } 25 | 26 | public int Execute( Type elementType, Expression predicate ) 27 | { 28 | SqlServerDeleteCommandBuilder deleteBuilder = new SqlServerDeleteCommandBuilder( elementType.Name ); 29 | 30 | if( predicate != null ) 31 | { 32 | SqlServerWherePartsCommandBuilder whereBuilder = new SqlServerWherePartsCommandBuilder( deleteBuilder.Parameters ); 33 | 34 | Expression expression = PartialEvaluatingExpressionTreeVisitor.EvaluateIndependentSubtrees( predicate ); 35 | 36 | SqlServerWhereClauseVisitor visitor = new SqlServerWhereClauseVisitor(); 37 | 38 | visitor.Translate( expression, whereBuilder ); 39 | 40 | deleteBuilder.WhereParts = whereBuilder.WherePartsBuilder.ToString(); 41 | } 42 | 43 | this.sessionProvider.ExecutedCommandBuilder = deleteBuilder; 44 | 45 | return this.sessionProvider.ExecuteNonQuery( deleteBuilder ); 46 | } 47 | 48 | public IDeleteable CreateDelete() 49 | { 50 | return new SqlServerDeleteable( this ); 51 | } 52 | 53 | public int Execute( Expression predicate ) 54 | { 55 | return Execute( typeof( T ), predicate ); 56 | } 57 | 58 | #endregion 59 | } 60 | } 61 | 62 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.SqlServer/Linq/SqlServerDeleteable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq.Expressions; 4 | using Remotion.Linq.Parsing.ExpressionTreeVisitors; 5 | using Restful.Linq; 6 | using Restful.Data.SqlServer.CommandBuilders; 7 | using Restful.Data.SqlServer.Visitors; 8 | 9 | namespace Restful.Data.SqlServer.Linq 10 | { 11 | public class SqlServerDeleteable : IDeleteable 12 | { 13 | private readonly Type elementType; 14 | private readonly IDeleteProvider provider; 15 | 16 | public SqlServerDeleteable( IDeleteProvider provider ) 17 | { 18 | this.provider = provider; 19 | this.elementType = typeof( T ); 20 | } 21 | 22 | public SqlServerDeleteable( IDeleteProvider provider, Type elementType ) 23 | { 24 | this.provider = provider; 25 | this.elementType = elementType; 26 | } 27 | 28 | #region IDeleteable implementation 29 | 30 | public Type ElementType 31 | { 32 | get 33 | { 34 | return this.elementType; 35 | } 36 | } 37 | 38 | public Expression Predicate { get; set; } 39 | 40 | public IDeleteProvider Provider 41 | { 42 | get 43 | { 44 | return this.provider; 45 | } 46 | } 47 | 48 | #endregion 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.SqlServer/Linq/SqlServerInsertProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Linq.Expressions; 5 | using System.Text; 6 | using Remotion.Linq.Parsing.ExpressionTreeVisitors; 7 | using Restful.Linq; 8 | using Restful.Data.SqlServer.CommandBuilders; 9 | using Restful.Data.SqlServer.Common; 10 | using Restful.Data.SqlServer.Visitors; 11 | 12 | namespace Restful.Data.SqlServer.Linq 13 | { 14 | public class SqlServerInsertProvider : IInsertProvider 15 | { 16 | private readonly ISessionProvider sessionProvider; 17 | 18 | public SqlServerInsertProvider( ISessionProvider sessionProvider ) 19 | { 20 | this.sessionProvider = sessionProvider; 21 | } 22 | 23 | public IInsertable CreateInsert( Type elementType ) 24 | { 25 | return (IInsertable)Activator.CreateInstance( typeof( SqlServerInsertable<> ).MakeGenericType( elementType ), new object[] { this, elementType } ); 26 | } 27 | 28 | public int Execute( Type elementType, IDictionary properties ) 29 | { 30 | SqlServerInsertCommandBuilder insertBuilder = new SqlServerInsertCommandBuilder( elementType.Name ); 31 | 32 | foreach( var item in properties ) 33 | { 34 | insertBuilder.AddColumn( item.Key.Member.Name, item.Value ); 35 | } 36 | 37 | this.sessionProvider.ExecutedCommandBuilder = insertBuilder; 38 | 39 | return this.sessionProvider.ExecuteNonQuery( insertBuilder ); 40 | } 41 | 42 | public IInsertable CreateInsert() 43 | { 44 | return new SqlServerInsertable( this ); 45 | } 46 | 47 | public int Execute( IDictionary properties ) 48 | { 49 | return this.Execute( typeof( T ), properties ); 50 | } 51 | } 52 | } 53 | 54 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.SqlServer/Linq/SqlServerInsetable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | using Remotion.Linq.Parsing.ExpressionTreeVisitors; 4 | using Restful.Data.SqlServer.CommandBuilders; 5 | using Restful.Data.SqlServer.Visitors; 6 | using System.Collections.Generic; 7 | using Restful.Linq; 8 | 9 | namespace Restful.Data.SqlServer.Linq 10 | { 11 | public class SqlServerInsertable : IInsertable 12 | { 13 | private readonly Type elementType; 14 | private readonly IDictionary properties; 15 | private readonly IInsertProvider provider; 16 | 17 | public SqlServerInsertable( IInsertProvider provider ) 18 | { 19 | this.provider = provider; 20 | this.elementType = typeof( T ); 21 | this.properties = new Dictionary(); 22 | } 23 | 24 | public SqlServerInsertable( IInsertProvider provider, Type elementType ) 25 | { 26 | this.provider = provider; 27 | this.elementType = elementType; 28 | this.properties = new Dictionary(); 29 | } 30 | 31 | #region IInsertable implementation 32 | 33 | public Type ElementType 34 | { 35 | get 36 | { 37 | return this.elementType; 38 | } 39 | } 40 | 41 | public IDictionary Properties 42 | { 43 | get 44 | { 45 | return this.properties; 46 | } 47 | } 48 | 49 | 50 | public IInsertProvider Provider 51 | { 52 | get 53 | { 54 | return this.provider; 55 | } 56 | } 57 | 58 | #endregion 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.SqlServer/Linq/SqlServerQueryExecutor.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Data; 3 | using System.Data.Common; 4 | using Remotion.Linq; 5 | using Restful.Data.SqlServer.Visitors; 6 | using System; 7 | 8 | namespace Restful.Data.SqlServer.Linq 9 | { 10 | public class SqlServerQueryExecutor : IQueryExecutor 11 | { 12 | protected ISessionProvider provider; 13 | 14 | public SqlServerQueryExecutor( ISessionProvider provider ) 15 | { 16 | this.provider = provider; 17 | } 18 | 19 | #region ExecuteCollection 20 | 21 | /// 22 | /// 执行查询,并返回 IEnumerable 对象 23 | /// 24 | /// 25 | /// 26 | /// 27 | public IEnumerable ExecuteCollection( QueryModel queryModel ) 28 | { 29 | SqlServerQueryModelVisitor queryModelVisitor = new SqlServerQueryModelVisitor(); 30 | 31 | var command = queryModelVisitor.Translate( queryModel ); 32 | 33 | this.provider.ExecutedCommandBuilder = command; 34 | 35 | using( IDataReader reader = this.provider.ExecuteDataReader( command ) ) 36 | { 37 | var tuple = reader.GetDeserializerState(); 38 | 39 | while( reader.Read() ) 40 | { 41 | yield return (T)tuple.Func( reader ); 42 | } 43 | } 44 | } 45 | 46 | #endregion 47 | 48 | #region ExecuteScalar 49 | 50 | /// 51 | /// 执行查询,并返回第一行第一列 52 | /// 53 | /// 54 | /// 55 | /// 56 | public T ExecuteScalar( QueryModel queryModel ) 57 | { 58 | SqlServerQueryModelVisitor queryModelVisitor = new SqlServerQueryModelVisitor(); 59 | 60 | var command = queryModelVisitor.Translate( queryModel ); 61 | 62 | this.provider.ExecutedCommandBuilder = command; 63 | 64 | return this.provider.ExecuteScalar( command ); 65 | } 66 | 67 | #endregion 68 | 69 | #region ExecuteSingle 70 | 71 | /// 72 | /// 执行查询,并返回单个对象 73 | /// 74 | /// 75 | /// 76 | /// 77 | /// 78 | public T ExecuteSingle( QueryModel queryModel, bool returnDefaultWhenEmpty ) 79 | { 80 | SqlServerQueryModelVisitor queryModelVisitor = new SqlServerQueryModelVisitor(); 81 | 82 | var command = queryModelVisitor.Translate( queryModel ); 83 | 84 | this.provider.ExecutedCommandBuilder = command; 85 | 86 | using( IDataReader reader = this.provider.ExecuteDataReader( command ) ) 87 | { 88 | bool isExists = reader.Read(); 89 | 90 | // 如果不存在查询记录 91 | if( isExists == false ) 92 | { 93 | // 如果可以默认 94 | if( returnDefaultWhenEmpty ) 95 | { 96 | return default( T ); 97 | } 98 | else 99 | { 100 | throw new InvalidOperationException( "未查询出满足条件的任何记录。" ); 101 | } 102 | } 103 | 104 | var tuple = reader.GetDeserializerState(); 105 | 106 | return (T)tuple.Func( reader ); 107 | } 108 | } 109 | 110 | #endregion 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.SqlServer/Linq/SqlServerQueryable.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Linq.Expressions; 3 | using Remotion.Linq; 4 | using Remotion.Linq.Parsing.Structure; 5 | 6 | namespace Restful.Data.SqlServer.Linq 7 | { 8 | public class SqlServerQueryable : QueryableBase 9 | { 10 | public SqlServerQueryable( IQueryParser queryParser, IQueryExecutor executor ) 11 | : base( new DefaultQueryProvider( typeof( SqlServerQueryable<> ), queryParser, executor ) ) 12 | { 13 | } 14 | 15 | public SqlServerQueryable( IQueryProvider provider, Expression expression ) 16 | : base( provider, expression ) 17 | { 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.SqlServer/Linq/SqlServerUpdateProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Restful.Linq; 3 | using System.Linq.Expressions; 4 | using Remotion.Linq.Parsing.ExpressionTreeVisitors; 5 | using Restful.Data.SqlServer.Visitors; 6 | using Restful.Data.SqlServer.CommandBuilders; 7 | using System.Collections.Generic; 8 | using System.Text; 9 | using System.Collections; 10 | using Restful.Data.SqlServer.Common; 11 | 12 | namespace Restful.Data.SqlServer.Linq 13 | { 14 | public class SqlServerUpdateProvider : IUpdateProvider 15 | { 16 | private readonly ISessionProvider sessionProvider; 17 | 18 | public SqlServerUpdateProvider( ISessionProvider sessionProvider ) 19 | { 20 | this.sessionProvider = sessionProvider; 21 | } 22 | 23 | public IUpdateable CreateUpdate( Type elementType ) 24 | { 25 | return (IUpdateable)Activator.CreateInstance( typeof( SqlServerUpdateable<> ).MakeGenericType( elementType ), new object[] { this, elementType } ); 26 | } 27 | 28 | public IUpdateable CreateUpdate() 29 | { 30 | return new SqlServerUpdateable( this ); 31 | } 32 | 33 | public int Execute( Type elementType, IDictionary properties, Expression predicate ) 34 | { 35 | SqlServerUpdateCommandBuilder updateBuilder = new SqlServerUpdateCommandBuilder( elementType.Name ); 36 | 37 | foreach( var item in properties ) 38 | { 39 | updateBuilder.AddColumn( item.Key.Member.Name, item.Value ); 40 | } 41 | 42 | if( predicate != null ) 43 | { 44 | SqlServerWherePartsCommandBuilder whereBuider = new SqlServerWherePartsCommandBuilder( updateBuilder.Parameters ); 45 | 46 | Expression expression = PartialEvaluatingExpressionTreeVisitor.EvaluateIndependentSubtrees( predicate ); 47 | 48 | SqlServerWhereClauseVisitor visitor = new SqlServerWhereClauseVisitor(); 49 | 50 | visitor.Translate( expression, whereBuider ); 51 | 52 | updateBuilder.WhereParts = whereBuider.WherePartsBuilder.ToString(); 53 | } 54 | 55 | this.sessionProvider.ExecutedCommandBuilder = updateBuilder; 56 | 57 | return this.sessionProvider.ExecuteNonQuery( updateBuilder ); 58 | } 59 | 60 | public int Execute( IDictionary properties, Expression predicate ) 61 | { 62 | return this.Execute( typeof( T ), properties, predicate ); 63 | } 64 | 65 | } 66 | } 67 | 68 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.SqlServer/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | 4 | // Information about this assembly is defined by the following attributes. 5 | // Change them to the values specific to your project. 6 | 7 | [assembly: AssemblyTitle( "Restful.Data.SqlServer" )] 8 | [assembly: AssemblyDescription( "" )] 9 | [assembly: AssemblyConfiguration( "" )] 10 | [assembly: AssemblyCompany( "" )] 11 | [assembly: AssemblyProduct( "" )] 12 | [assembly: AssemblyCopyright( "zhaogh" )] 13 | [assembly: AssemblyTrademark( "" )] 14 | [assembly: AssemblyCulture( "" )] 15 | 16 | // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". 17 | // The form "{Major}.{Minor}.*" will automatically update the build and revision, 18 | // and "{Major}.{Minor}.{Build}.*" will update just the revision. 19 | 20 | [assembly: AssemblyVersion( "1.0.*" )] 21 | 22 | // The following attributes are used to specify the signing key for the assembly, 23 | // if desired. See the Mono documentation for more information about signing. 24 | 25 | //[assembly: AssemblyDelaySign(false)] 26 | //[assembly: AssemblyKeyFile("")] 27 | 28 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.SqlServer/Restful.Data.SqlServer.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | {E421F9CE-9BD9-4A85-8CF4-4919B013063E} 7 | Library 8 | Restful.Data.SqlServer 9 | Restful.Data.SqlServer 10 | 2.0 11 | 12 | 13 | true 14 | full 15 | false 16 | ..\..\..\lib 17 | DEBUG; 18 | prompt 19 | 4 20 | false 21 | 22 | 23 | full 24 | true 25 | ..\..\..\lib 26 | prompt 27 | 4 28 | false 29 | 30 | 31 | 32 | 33 | 34 | ..\References\Remotion.Linq.dll 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | {39D214BE-3A4A-4174-8C53-5B7B5654D1AA} 76 | Restful.Linq 77 | 78 | 79 | {4BA05EF7-5312-4B37-B0A2-07E68DD05BEA} 80 | Restful.Data 81 | 82 | 83 | {ECEDCBF3-7039-4A01-B87A-DA84DA939404} 84 | Restful 85 | 86 | 87 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.SqlServer/SqlServerSession.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Restful.Data.SqlServer 7 | { 8 | public class SqlServerSession : ISession 9 | { 10 | private SqlServerSessionProvider provider; 11 | 12 | public SqlServerSession( ISessionProviderFactory factory, string connectionStr ) 13 | { 14 | this.provider = new SqlServerSessionProvider( factory, connectionStr ); 15 | } 16 | 17 | public int CommandTimeout 18 | { 19 | get 20 | { 21 | return this.provider.CommandTimeout; 22 | } 23 | set 24 | { 25 | this.provider.CommandTimeout = value; 26 | } 27 | } 28 | 29 | public ISessionProvider Provider 30 | { 31 | get { return this.provider; } 32 | } 33 | 34 | public void Dispose() 35 | { 36 | this.provider.Dispose(); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.SqlServer/SqlServerSessionProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Data; 4 | using System.Data.Common; 5 | using System.Diagnostics; 6 | using System.Linq; 7 | using System.Reflection; 8 | using System.Text; 9 | using Remotion.Linq.Parsing.Structure; 10 | using Restful; 11 | using Restful.Data; 12 | using Restful.Data.SqlServer.Common; 13 | using Restful.Data.SqlServer.Linq; 14 | 15 | namespace Restful.Data.SqlServer 16 | { 17 | public class SqlServerSessionProvider : SessionProvider 18 | { 19 | #region SqlServerSessionProvider 20 | 21 | /// 22 | /// 构造函数 23 | /// 24 | /// 25 | public SqlServerSessionProvider( ISessionProviderFactory factory, string connectionStr ) : base( factory, connectionStr ) 26 | { 27 | 28 | } 29 | 30 | #endregion 31 | 32 | #region ExecuteDataPage 33 | 34 | /// 35 | /// 执行分页查询 36 | /// 37 | /// SQL 语句 38 | /// 页索引 39 | /// 页大小 40 | /// 排序字段 41 | /// 参数列表 42 | /// 分页查询结果 43 | public override DataPage ExecuteDataPage( CommandBuilder command, int pageIndex, int pageSize, string orderBy ) 44 | { 45 | if( string.IsNullOrEmpty( orderBy ) ) 46 | { 47 | throw new ArgumentNullException( "orderBy" ); 48 | } 49 | 50 | DataPage dataPage = new DataPage( pageIndex, pageSize ); 51 | 52 | #region 查询满足条件的条目数量 53 | string queryItemCountSql = string.Format( "SELECT COUNT(*) FROM ( {0} ) T1", command.ToString() ); 54 | 55 | dataPage.ItemCount = this.ExecuteScalar( new Restful.Data.SqlServer.CommandBuilders.SqlServerCommandBuilder( queryItemCountSql, command.Parameters ) ); 56 | 57 | if( dataPage.ItemCount == 0 ) // 如果满足条件的数据条目数量为零,则重置页索引为 1 58 | { 59 | dataPage.PageIndex = 1; 60 | } 61 | else if( dataPage.PageIndex > dataPage.PageCount ) // 如果指定的页索引大于查询直接总页数,则重置页索引为总页数 62 | { 63 | dataPage.PageIndex = dataPage.PageCount; 64 | } 65 | #endregion 66 | 67 | #region 查询最终的结果集 68 | 69 | string limitFrom = string.Format( "{0}LimitFrom", Constants.ParameterPrefix ); 70 | string limitTo = string.Format( "{0}LimitTo", Constants.ParameterPrefix ); 71 | 72 | command.Parameters.Add( limitFrom, ( dataPage.PageIndex - 1 ) * dataPage.PageSize + 1 ); 73 | command.Parameters.Add( limitTo, dataPage.PageIndex * dataPage.PageSize ); 74 | 75 | string queryItemSql = string.Format( "select * from ( select *, row_number() over( order by {0} ) as RowNumber from ( {1} ) a ) t where RowNumber between {2} and {3} ", orderBy, command.ToString(), limitFrom, limitTo ); 76 | 77 | dataPage.Data = this.ExecuteDataTable( new Restful.Data.SqlServer.CommandBuilders.SqlServerCommandBuilder( queryItemSql, command.Parameters ) ); 78 | #endregion 79 | 80 | return dataPage; 81 | } 82 | 83 | #endregion 84 | 85 | #region GetIdentifier 86 | 87 | /// 88 | /// 获取最新插入数据的自增ID 89 | /// 90 | /// 91 | /// 92 | public override T GetIdentifier() 93 | { 94 | return this.ExecuteScalar( new Restful.Data.SqlServer.CommandBuilders.SqlServerCommandBuilder( "select @@identity" ) ); 95 | } 96 | 97 | #endregion 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.SqlServer/SqlServerSessionProviderFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Data; 6 | using System.Data.Common; 7 | using Restful.Data.SqlServer.Linq; 8 | using Remotion.Linq.Parsing.Structure; 9 | using Remotion.Linq; 10 | using Restful.Data.SqlServer.CommandBuilders; 11 | using Restful.Data.SqlServer.Visitors; 12 | using Restful.Linq; 13 | using System.Data.SqlClient; 14 | 15 | namespace Restful.Data.SqlServer 16 | { 17 | public class SqlServerSessionProviderFactory : ISessionProviderFactory 18 | { 19 | public CommandBuilder CreateCommandBuilder() 20 | { 21 | return new Restful.Data.SqlServer.CommandBuilders.SqlServerCommandBuilder(); 22 | } 23 | 24 | public IUpdateProvider CreateUpdateProvider( ISessionProvider provider ) 25 | { 26 | return new SqlServerUpdateProvider( provider ); 27 | } 28 | 29 | public IInsertProvider CreateInsertProvider( ISessionProvider provider ) 30 | { 31 | return new SqlServerInsertProvider( provider ); 32 | } 33 | 34 | public IDeleteProvider CreateDeleteProvider( ISessionProvider provider ) 35 | { 36 | return new SqlServerDeleteProvider( provider ); 37 | } 38 | 39 | public ISession CreateSession( string connectionStr ) 40 | { 41 | return new SqlServerSession( this, connectionStr ); 42 | } 43 | 44 | public DbConnection CreateConnection( string connectionStr ) 45 | { 46 | return new SqlConnection( connectionStr ); 47 | } 48 | 49 | public DbDataAdapter CreateDataAdapter() 50 | { 51 | return new SqlDataAdapter(); 52 | } 53 | 54 | public IQueryable CreateQueryable( ISessionProvider provider ) 55 | { 56 | return new SqlServerQueryable( QueryParser.CreateDefault(), new SqlServerQueryExecutor( provider ) ); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data.SqlServer/Visitors/SqlServerOrderByClauseVisitor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq.Expressions; 4 | using System.Text; 5 | using Remotion.Linq.Clauses.ExpressionTreeVisitors; 6 | using Remotion.Linq.Clauses.Expressions; 7 | using Remotion.Linq.Parsing; 8 | using Restful.Data.SqlServer.Common; 9 | using Restful.Data.SqlServer.CommandBuilders; 10 | 11 | namespace Restful.Data.SqlServer.Visitors 12 | { 13 | internal class SqlServerOrderByClauseVisitor : ThrowingExpressionTreeVisitor 14 | { 15 | private SqlServerOrderByPartsCommandBuilder commandBuilder; 16 | 17 | #region OrderByClauseVisitor 18 | 19 | /// 20 | /// 构造函数 21 | /// 22 | public SqlServerOrderByClauseVisitor() 23 | { 24 | } 25 | 26 | #endregion 27 | 28 | #region Translate 29 | 30 | /// 31 | /// 翻译表达式 32 | /// 33 | /// 34 | public void Translate( Expression expression, SqlServerOrderByPartsCommandBuilder commandBuilder ) 35 | { 36 | this.commandBuilder = commandBuilder; 37 | 38 | this.VisitExpression( expression ); 39 | } 40 | 41 | #endregion 42 | 43 | #region VisitQuerySourceReferenceExpression 44 | 45 | /// 46 | /// 解析查询源引用表达式 47 | /// 48 | /// 49 | /// 50 | protected override Expression VisitQuerySourceReferenceExpression( QuerySourceReferenceExpression expression ) 51 | { 52 | this.commandBuilder.OrderByParts.Append( expression.ReferencedQuerySource.ItemName.ToLower() ); 53 | 54 | return expression; 55 | } 56 | 57 | #endregion 58 | 59 | #region VisitMemberExpression 60 | 61 | /// 62 | /// 解析成员访问表达式 63 | /// 64 | /// 65 | /// 66 | protected override Expression VisitMemberExpression( MemberExpression expression ) 67 | { 68 | this.VisitExpression( expression.Expression ); 69 | 70 | this.commandBuilder.OrderByParts.AppendFormat( ".{0}{1}{2}", Constants.LeftQuote, expression.Member.Name, Constants.RightQuote ); 71 | 72 | return expression; 73 | } 74 | 75 | #endregion 76 | 77 | #region CreateUnhandledItemException 78 | 79 | protected override Exception CreateUnhandledItemException( T unhandledItem, string visitMethod ) 80 | { 81 | string itemText = FormatUnhandledItem( unhandledItem ); 82 | var message = string.Format( "The expression '{0}' (type: {1}) is not supported by this LINQ provider.", itemText, typeof( T ) ); 83 | return new NotSupportedException( message ); 84 | } 85 | 86 | #endregion 87 | 88 | #region FormatUnhandledItem 89 | 90 | private string FormatUnhandledItem( T unhandledItem ) 91 | { 92 | var itemAsExpression = unhandledItem as Expression; 93 | return itemAsExpression != null ? FormattingExpressionTreeVisitor.Format( itemAsExpression ) : unhandledItem.ToString(); 94 | } 95 | 96 | #endregion 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data/Attributes/AutoIncreaseAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Restful.Data.Attributes 7 | { 8 | /// 9 | /// 标记属性对应的数据库字段是否为自增长 10 | /// 11 | [AttributeUsage( AttributeTargets.Property, Inherited = true )] 12 | public class AutoIncreaseAttribute : Attribute 13 | { 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data/Attributes/PrimaryKeyAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Restful.Data.Attributes 7 | { 8 | /// 9 | /// 标记属性对应的数据库字段是否为主键 10 | /// 11 | [AttributeUsage( AttributeTargets.Property, Inherited = true )] 12 | public class PrimaryKeyAttribute : Attribute 13 | { 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data/CommandBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using System.Collections.Generic; 4 | using Remotion.Linq.Clauses.ResultOperators; 5 | using System.Collections; 6 | 7 | namespace Restful.Data 8 | { 9 | /// 10 | /// SQL 命令构造器 11 | /// 12 | public abstract class CommandBuilder 13 | { 14 | #region Members 15 | 16 | /// 17 | /// 参数列表 18 | /// 19 | protected IDictionary parameters; 20 | 21 | #endregion 22 | 23 | #region Properties 24 | 25 | /// 26 | /// 获取 SQL 语句 27 | /// 28 | /// The sql. 29 | public abstract string Sql { get; set; } 30 | 31 | /// 32 | /// 获取 SQL 命令构造器中的参数列表 33 | /// 34 | /// The parameters. 35 | public IDictionary Parameters { get { return this.parameters; } } 36 | 37 | #endregion 38 | 39 | #region Constructor 40 | 41 | public CommandBuilder() 42 | { 43 | this.parameters = new Dictionary(); 44 | } 45 | 46 | public CommandBuilder( IDictionary parameters ) 47 | { 48 | this.parameters = parameters; 49 | } 50 | 51 | #endregion 52 | 53 | #region AddParameter 54 | 55 | /// 56 | /// 添加命名参数 57 | /// 58 | /// 参数名 59 | /// 参数值 60 | public virtual void AddParameter( string parameterName, object value ) 61 | { 62 | this.parameters.Add( parameterName, value ); 63 | } 64 | 65 | /// 66 | /// 添加匿名参数 67 | /// 68 | /// 参数名 69 | /// 参数值 70 | public abstract string AddParameter( object value ); 71 | 72 | #endregion 73 | 74 | #region ToString 75 | 76 | /// 77 | /// 重载基类 ToString 方法 78 | /// 79 | /// SQL 语句 80 | public override string ToString() 81 | { 82 | return this.Sql; 83 | } 84 | 85 | #endregion 86 | } 87 | } 88 | 89 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data/CommandParameter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Data; 4 | 5 | namespace Restful.Data 6 | { 7 | /// 8 | /// 命令参数 9 | /// 10 | public class CommandParameter 11 | { 12 | #region Properties 13 | 14 | /// 15 | /// 获取或设置参数名称 16 | /// 17 | public string ParameterName { get; set; } 18 | 19 | /// 20 | /// 获取或设置参数方向 21 | /// 22 | public ParameterDirection Direction { get; set; } 23 | 24 | /// 25 | /// 获取或设置参数大小 26 | /// 27 | public int Size { get; set; } 28 | 29 | /// 30 | /// 获取或设置参数值 31 | /// 32 | /// The value. 33 | public object Value { get; set; } 34 | 35 | #endregion 36 | 37 | #region Constructor 38 | 39 | /// 40 | /// 构造函数 41 | /// 42 | public CommandParameter() 43 | { 44 | 45 | } 46 | 47 | /// 48 | /// 构造函数 49 | /// 50 | /// 参数名 51 | public CommandParameter( string parameterName ) 52 | { 53 | this.ParameterName = parameterName; 54 | } 55 | 56 | public CommandParameter( string parameterName, object value ) 57 | { 58 | this.ParameterName = parameterName; 59 | this.Value = value; 60 | } 61 | 62 | #endregion 63 | } 64 | } 65 | 66 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data/DataPage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Data; 4 | using System.Linq; 5 | using System.Text; 6 | 7 | namespace Restful.Data 8 | { 9 | /// 10 | /// 分页查询数据 11 | /// 12 | public class DataPage 13 | { 14 | #region Members 15 | 16 | private int m_PageIndex = 1; 17 | private int m_PageSize = 20; 18 | private int m_ItemCount = 0; 19 | 20 | #endregion 21 | 22 | #region Properties 23 | 24 | /// 25 | /// 获取或设置页索引,设置 PageIndex 时,值必须大于零。 26 | /// 27 | public int PageIndex 28 | { 29 | get 30 | { 31 | return this.m_PageIndex; 32 | } 33 | set 34 | { 35 | if( value <= 0 ) 36 | { 37 | throw new ArgumentOutOfRangeException( "PageIndex 的值必须大于零。" ); 38 | } 39 | 40 | this.m_PageIndex = value; 41 | } 42 | } 43 | 44 | /// 45 | /// 获取或设置页大小,设置 PageSize 时,值必须大于零 46 | /// 47 | public int PageSize 48 | { 49 | get 50 | { 51 | return this.m_PageSize; 52 | } 53 | set 54 | { 55 | if( value <= 0 ) 56 | { 57 | throw new ArgumentOutOfRangeException( "PageSize 的值必须大于零。" ); 58 | } 59 | 60 | this.m_PageSize = value; 61 | } 62 | } 63 | 64 | /// 65 | /// 获取或设置总条目数 66 | /// 67 | public int ItemCount 68 | { 69 | get 70 | { 71 | return this.m_ItemCount; 72 | } 73 | set 74 | { 75 | if( value < 0 ) 76 | { 77 | throw new ArgumentOutOfRangeException( "ItemCount 的值必须大于或等于零。" ); 78 | } 79 | 80 | this.m_ItemCount = value; 81 | } 82 | } 83 | 84 | /// 85 | /// 获取总页数,当 ItemCount = 0 时,PageCount 默认为 1 86 | /// 87 | public int PageCount 88 | { 89 | get 90 | { 91 | if( this.m_ItemCount == 0 ) 92 | return 1; 93 | 94 | return ( this.m_ItemCount - 1 ) / this.PageSize + 1; 95 | } 96 | } 97 | 98 | /// 99 | /// 获取或设置分页查询结果数据 100 | /// 101 | /// The data. 102 | public DataTable Data { get; set; } 103 | 104 | #endregion 105 | 106 | #region Constructor 107 | 108 | /// 109 | /// 构造函数 110 | /// 111 | /// 页索引 112 | /// 页大小 113 | public DataPage( int pageIndex, int pageSize ) 114 | { 115 | this.PageIndex = pageIndex; 116 | this.PageSize = pageSize; 117 | } 118 | 119 | #endregion 120 | 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data/EntityHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Castle.DynamicProxy; 3 | using System.Reflection; 4 | using Restful.Reflection.Emit; 5 | using System.Security; 6 | 7 | namespace Restful.Data 8 | { 9 | /// 10 | /// 实体代理对象生成器 11 | /// 12 | public static class EntityHelper 13 | { 14 | #region Constants 15 | 16 | private const string ASSEMBLY_NAME = "Restful.Data.Entity.Proxies.dll"; 17 | private const string MODULE_PATH = "Restful.Data.Entity.Proxies"; 18 | 19 | #endregion 20 | 21 | #region Members 22 | 23 | private static ProxyGenerator generator; 24 | 25 | #endregion 26 | 27 | #region Constructor 28 | 29 | static EntityHelper() 30 | { 31 | var scope = new ModuleScope( false, false, new EntityProxyNameScope(), ASSEMBLY_NAME, MODULE_PATH, ASSEMBLY_NAME, MODULE_PATH ); 32 | 33 | generator = new ProxyGenerator( new DefaultProxyBuilder( scope ) ); 34 | } 35 | 36 | #endregion 37 | 38 | #region CreateProxy 39 | 40 | /// 41 | /// 创建指定类型的实体代理对象 42 | /// 43 | /// 实体代理对象 44 | /// 类型 45 | public static object CreateProxy( Type @type ) 46 | { 47 | ProxyGenerationOptions options = new ProxyGenerationOptions( new EntityInterceptorFilter() ) { Selector = new EntityInterceptorSelector() }; 48 | 49 | options.AddMixinInstance( new EntityObject() ); 50 | 51 | object target = generator.CreateClassProxy( @type, options, new EntityInterceptor() ); 52 | 53 | ( (IEntityObject)target ).Reset(); 54 | 55 | return target; 56 | } 57 | 58 | /// 59 | /// 创建指定类型的实体代理对象 60 | /// 61 | /// 实体代理对象 62 | /// 类型 63 | public static T CreateProxy() 64 | { 65 | return (T)CreateProxy( typeof( T ) ); 66 | //return (T)generator.CreateClassProxy( typeof( T ), options, new EntityInterceptor() ); 67 | } 68 | 69 | /// 70 | /// 创建指定对象的实体代理对象 71 | /// 72 | /// 实体代理对象 73 | /// 对象 74 | public static object CreateProxy( object @object ) 75 | { 76 | object target = CreateProxy( @object.GetType() ); 77 | 78 | var handler = DynamicHelper.CreateDynamicMapHandler( @object.GetType(), target.GetType() ); 79 | 80 | handler( @object, target ); 81 | 82 | ( (IEntityObject)target ).Reset(); 83 | 84 | return target; 85 | } 86 | 87 | /// 88 | /// 创建指定对象的实体代理对象 89 | /// 90 | /// 实体代理对象 91 | /// 对象 92 | /// 93 | public static T CreateProxy( T @object ) 94 | { 95 | T target = CreateProxy(); 96 | 97 | var handler = DynamicHelper.CreateDynamicMapHandler( typeof( T ), target.GetType() ); 98 | 99 | handler( @object, target ); 100 | 101 | ( (IEntityObject)target ).Reset(); 102 | 103 | return target; 104 | } 105 | 106 | #endregion 107 | 108 | #region CompileDynamicProxyTypes 109 | 110 | /// 111 | /// 编译实体动态代理并缓存 112 | /// 113 | /// Types. 114 | public static void CompileDynamicProxyTypes( params Type[] types ) 115 | { 116 | if( types == null || types.Length == 0 ) 117 | { 118 | return; 119 | } 120 | 121 | foreach( var type in types ) 122 | { 123 | var @object = Activator.CreateInstance( type ); 124 | 125 | var proxy = CreateProxy( @object ); 126 | 127 | @object = null; 128 | 129 | proxy = null; 130 | } 131 | } 132 | 133 | #endregion 134 | } 135 | } 136 | 137 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data/EntityInterceptor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Castle.DynamicProxy; 3 | 4 | namespace Restful.Data 5 | { 6 | public class EntityInterceptor : IInterceptor 7 | { 8 | public void Intercept( IInvocation invocation ) 9 | { 10 | var @object = (IEntityObject)invocation.InvocationTarget; 11 | 12 | @object.OnPropertyChanged( invocation.Method.Name.Replace( "set_", "" ) ); 13 | 14 | invocation.Proceed(); 15 | } 16 | } 17 | } 18 | 19 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data/EntityInterceptorFilter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Castle.DynamicProxy; 3 | using System.Reflection; 4 | 5 | namespace Restful.Data 6 | { 7 | public class EntityInterceptorFilter : IProxyGenerationHook 8 | { 9 | public void NonProxyableMemberNotification( Type type, MemberInfo memberInfo ) 10 | { 11 | throw new NotImplementedException(); 12 | } 13 | 14 | public void NonVirtualMemberNotification( Type type, MemberInfo memberInfo ) 15 | { 16 | } 17 | 18 | public void MethodsInspected() 19 | { 20 | } 21 | 22 | public bool ShouldInterceptMethod( Type type, MethodInfo memberInfo ) 23 | { 24 | return memberInfo.IsSpecialName && ( memberInfo.Name.StartsWith( "set_" ) || memberInfo.Name.StartsWith( "get_" ) ); 25 | } 26 | } 27 | } 28 | 29 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data/EntityInterceptorSelector.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using Castle.DynamicProxy; 4 | 5 | namespace Restful.Data 6 | { 7 | public class EntityInterceptorSelector : IInterceptorSelector 8 | { 9 | public IInterceptor[] SelectInterceptors( Type type, MethodInfo method, IInterceptor[] interceptors ) 10 | { 11 | if( method.Name.StartsWith( "set_" ) ) 12 | return interceptors; 13 | 14 | return null; 15 | } 16 | } 17 | } 18 | 19 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data/EntityObject.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | 5 | namespace Restful.Data 6 | { 7 | /// 8 | /// 实体对象类型基类 9 | /// 10 | [Serializable] 11 | public class EntityObject : IEntityObject, INotifyPropertyChanged 12 | { 13 | /// 14 | /// 属性改变事件 15 | /// 16 | public event PropertyChangedEventHandler PropertyChanged; 17 | 18 | #region Properties 19 | 20 | /// 21 | /// 获取或设置已改变的属性集合 22 | /// 23 | public IList ChangedProperties { get; private set; } 24 | 25 | #endregion 26 | 27 | #region EntityObject 28 | 29 | /// 30 | /// 基类构造方法 31 | /// 32 | public EntityObject() 33 | { 34 | this.ChangedProperties = new List(); 35 | } 36 | 37 | #endregion 38 | 39 | #region OnPropertyChanged 40 | 41 | /// 42 | /// 处理实体对象的属性值改变事件 43 | /// 44 | /// 属性名 45 | public void OnPropertyChanged( string propertyName ) 46 | { 47 | if( this.ChangedProperties.Contains( propertyName ) == false ) 48 | { 49 | this.ChangedProperties.Add( propertyName ); 50 | } 51 | 52 | if( this.PropertyChanged != null ) 53 | { 54 | this.PropertyChanged( this, new PropertyChangedEventArgs( propertyName ) ); 55 | } 56 | } 57 | 58 | #endregion 59 | 60 | #region Reset 61 | 62 | /// 63 | /// 清空已更新属性集合 64 | /// 65 | public void Reset() 66 | { 67 | this.ChangedProperties.Clear(); 68 | } 69 | 70 | #endregion 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data/EntityProxyNameScope.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Castle.DynamicProxy.Generators; 3 | using System.Collections.Generic; 4 | using System.Diagnostics; 5 | 6 | namespace Restful.Data 7 | { 8 | public class EntityProxyNameScope : INamingScope 9 | { 10 | private const string CASTLE_NAMESPACE = "Castle.Proxies."; 11 | private const string RESTFUL_NAMESPACE = "Restful.Data.Entity.Proxies."; 12 | 13 | private readonly IDictionary names = new Dictionary(); 14 | private readonly INamingScope parentScope; 15 | 16 | public INamingScope ParentScope 17 | { 18 | get 19 | { 20 | return this.parentScope; 21 | } 22 | } 23 | 24 | public EntityProxyNameScope() 25 | { 26 | } 27 | 28 | private EntityProxyNameScope( INamingScope parent ) 29 | { 30 | this.parentScope = parent; 31 | } 32 | 33 | public string GetUniqueName( string suggestedName ) 34 | { 35 | Debug.Assert( !string.IsNullOrEmpty( suggestedName ), "string.IsNullOrEmpty(suggestedName) == false" ); 36 | 37 | suggestedName = suggestedName.Replace( CASTLE_NAMESPACE, RESTFUL_NAMESPACE ); 38 | 39 | int counter; 40 | 41 | if( !this.names.TryGetValue( suggestedName, out counter ) ) 42 | { 43 | this.names.Add( suggestedName, 0 ); 44 | 45 | return suggestedName; 46 | } 47 | else 48 | { 49 | counter++; 50 | 51 | this.names[suggestedName] = counter; 52 | 53 | return suggestedName + "_" + counter.ToString(); 54 | } 55 | } 56 | 57 | public INamingScope SafeSubScope() 58 | { 59 | return new EntityProxyNameScope( this ); 60 | } 61 | } 62 | } 63 | 64 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data/Extensions/IDataReaderExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Data; 3 | using Restful.Data.Dapper; 4 | 5 | namespace System.Data 6 | { 7 | public static class IDataReaderExtensions 8 | { 9 | /// 10 | /// 获取 DeserializerState 对象 11 | /// 12 | /// 13 | /// 14 | /// 15 | public static SqlMapper.DeserializerState GetDeserializerState( this IDataReader reader ) 16 | { 17 | int hash = SqlMapper.GetColumnHash( reader ); 18 | 19 | return new SqlMapper.DeserializerState( hash, SqlMapper.GetDeserializer( typeof( T ), reader, 0, -1, false ) ); 20 | } 21 | } 22 | } 23 | 24 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data/Extensions/IUpdateableGenericExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Linq.Expressions; 5 | using System.Reflection; 6 | using Restful.Data; 7 | 8 | namespace Restful.Linq 9 | { 10 | public static class IUpdateableGenericExtensions 11 | { 12 | /// 13 | /// 设置需更新的实体对象 14 | /// 15 | /// source 16 | /// 需更新的实体对象 17 | /// 元素类型 18 | public static IUpdateable Set( this IUpdateable source, object @object ) 19 | { 20 | source.Properties.Clear(); 21 | 22 | IEntityObject entity = (IEntityObject)@object; 23 | 24 | Type elementType = @object.GetType().BaseType; 25 | 26 | var properties = @object.GetType().GetProperties( BindingFlags.Public | BindingFlags.Instance ); 27 | 28 | properties.Where( property => property.IsPrimaryKey() == false ).Each( property => 29 | { 30 | if( entity.ChangedProperties.Contains( property.Name ) ) 31 | { 32 | ParameterExpression pe = Expression.Parameter( @object.GetType(), "s" ); 33 | MemberExpression me = Expression.MakeMemberAccess( pe, property ); 34 | 35 | source.Set( me, property.EmitGetValue( @object ) ); 36 | } 37 | } ); 38 | 39 | return source; 40 | } 41 | } 42 | } 43 | 44 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data/Extensions/ObjectExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Restful.Data; 3 | 4 | namespace System 5 | { 6 | public static class ObjectExtensions 7 | { 8 | /// 9 | /// 将对象转换为实体代理 10 | /// 11 | /// 实体代理 12 | /// 对象 13 | /// 14 | public static T ToEntityProxy( this T @object ) where T : class 15 | { 16 | return EntityHelper.CreateProxy( @object ); 17 | } 18 | } 19 | } 20 | 21 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data/Extensions/PropertyInfoExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using Restful.Data.Attributes; 4 | 5 | namespace System.Reflection 6 | { 7 | public static class PropertyInfoExtensions 8 | { 9 | 10 | #region PropertyInfo Extensions 11 | 12 | /// 13 | /// 判断属性是否为主键属性 14 | /// 15 | /// true if is primary key the specified property; otherwise, false. 16 | /// Property. 17 | public static bool IsPrimaryKey( this PropertyInfo property ) 18 | { 19 | return Attribute.GetCustomAttributes( property, typeof( PrimaryKeyAttribute ), true ).Length > 0; 20 | } 21 | 22 | /// 23 | /// 判断属性是否为自增长属性 24 | /// 25 | /// true if is auto increase the specified property; otherwise, false. 26 | /// Property. 27 | public static bool IsAutoIncrease( this PropertyInfo property ) 28 | { 29 | return Attribute.GetCustomAttributes( property, typeof( AutoIncreaseAttribute ), true ).Length > 0; 30 | } 31 | 32 | #endregion 33 | } 34 | } 35 | 36 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data/IEntityObject.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Restful.Data 5 | { 6 | /// 7 | /// 实体接口 8 | /// 9 | public interface IEntityObject 10 | { 11 | /// 12 | /// 获取已改变的属性集合 13 | /// 14 | /// The changed properties. 15 | IList ChangedProperties { get; } 16 | 17 | /// 18 | /// 当属性改变时记录属性名称 19 | /// 20 | /// Property name. 21 | void OnPropertyChanged( string propertyName ); 22 | 23 | /// 24 | /// 将已改变属性集合清空 25 | /// 26 | void Reset(); 27 | } 28 | } 29 | 30 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data/ISession.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Restful.Data 4 | { 5 | /// 6 | /// session 接口 7 | /// 8 | public interface ISession : IDisposable 9 | { 10 | /// 11 | /// 获取 Session 提供程序 12 | /// 13 | ISessionProvider Provider { get; } 14 | 15 | /// 16 | /// 获取和设置执行 SQL 命令的超时时间,单位秒 17 | /// 18 | /// The timeout. 19 | int CommandTimeout { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data/ISessionProviderFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Data.Common; 4 | using System.Linq; 5 | using System.Text; 6 | using Remotion.Linq; 7 | using Remotion.Linq.Parsing.Structure; 8 | using Restful.Linq; 9 | 10 | namespace Restful.Data 11 | { 12 | public interface ISessionProviderFactory 13 | { 14 | /// 15 | /// 创建 ISession 对象 16 | /// 17 | /// 连接字符串 18 | /// ISession 对象 19 | ISession CreateSession( string connectionStr ); 20 | 21 | /// 22 | /// 创建数据库连接对象 23 | /// 24 | /// 数据库连接对象 25 | /// 连接字符串 26 | DbConnection CreateConnection( string connectionStr ); 27 | 28 | /// 29 | /// 创建数据适配器 30 | /// 31 | DbDataAdapter CreateDataAdapter(); 32 | 33 | /// 34 | /// Creates the command builder. 35 | /// 36 | /// The command builder. 37 | CommandBuilder CreateCommandBuilder(); 38 | 39 | /// 40 | /// Creates the insert provider. 41 | /// 42 | /// The insert provider. 43 | /// Provider. 44 | IInsertProvider CreateInsertProvider( ISessionProvider provider ); 45 | 46 | /// 47 | /// Creates the delete provider. 48 | /// 49 | /// The delete provider. 50 | /// Provider. 51 | IDeleteProvider CreateDeleteProvider( ISessionProvider provider ); 52 | 53 | /// 54 | /// Creates the update provider. 55 | /// 56 | /// The update provider. 57 | /// Provider. 58 | IUpdateProvider CreateUpdateProvider( ISessionProvider provider ); 59 | 60 | /// 61 | /// Creates the queryable. 62 | /// 63 | /// The queryable. 64 | /// Query parser. 65 | /// Executor. 66 | /// The 1st type parameter. 67 | IQueryable CreateQueryable( ISessionProvider provider ); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的常规信息通过以下 6 | // 特性集控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle("Restful.Data")] 9 | [assembly: AssemblyDescription( "Restful.Data" )] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("zhaogh")] 12 | [assembly: AssemblyProduct("Restful.Data")] 13 | [assembly: AssemblyCopyright("Copyright © 2014")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // 将 ComVisible 设置为 false 使此程序集中的类型 18 | // 对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型, 19 | // 则将该类型上的 ComVisible 特性设置为 true。 20 | [assembly: ComVisible(false)] 21 | 22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 23 | [assembly: Guid("257f7c95-23bc-4bf0-87a7-f48bcfcced7d")] 24 | 25 | // 程序集的版本信息由下面四个值组成: 26 | // 27 | // 主版本 28 | // 次版本 29 | // 生成号 30 | // 修订号 31 | // 32 | // 可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值, 33 | // 方法是按如下所示使用“*”: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.1")] 36 | [assembly: AssemblyFileVersion("1.0.0.1")] 37 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data/Restful.Data.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {4BA05EF7-5312-4B37-B0A2-07E68DD05BEA} 8 | Library 9 | Properties 10 | Restful.Data 11 | Restful.Data 12 | v4.0 13 | 512 14 | 15 | 2.0 16 | 17 | 18 | true 19 | full 20 | false 21 | ..\..\..\lib 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | pdbonly 28 | true 29 | ..\..\..\lib 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | ..\References\Remotion.Linq.dll 43 | 44 | 45 | ..\References\Castle.Core.dll 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 86 | 87 | 88 | {ECEDCBF3-7039-4A01-B87A-DA84DA939404} 89 | Restful 90 | 91 | 92 | {39D214BE-3A4A-4174-8C53-5B7B5654D1AA} 93 | Restful.Linq 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data/SessionFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Data.Common; 7 | 8 | namespace Restful.Data 9 | { 10 | public static class SessionFactory 11 | { 12 | /// 13 | /// 获取或设置 Web.config 或 App.config 文件中配置的默认连接字符串节点名称 14 | /// 15 | public static string Default { get; set; } 16 | 17 | #region CreateDefaultSession 18 | 19 | /// 20 | /// 创建默认的 Session 21 | /// 22 | /// 23 | public static ISession CreateDefaultSession() 24 | { 25 | if( string.IsNullOrEmpty( Default ) == false ) 26 | { 27 | return CreateSession( Default ); 28 | } 29 | 30 | string providerName = ConfigurationManager.ConnectionStrings[0].ProviderName; 31 | string connectionString = ConfigurationManager.ConnectionStrings[0].ConnectionString; 32 | 33 | return CreateSession( providerName, connectionString ); 34 | } 35 | 36 | #endregion 37 | 38 | #region CreateSession 39 | 40 | /// 41 | /// 根据配置文件中指定的名称创建 Session 42 | /// 43 | /// 44 | /// 45 | public static ISession CreateSession( string name ) 46 | { 47 | string providerName = ConfigurationManager.ConnectionStrings[name].ProviderName; 48 | string connectionString = ConfigurationManager.ConnectionStrings[name].ConnectionString; 49 | 50 | return CreateSession( providerName, connectionString ); 51 | } 52 | 53 | /// 54 | /// 根据指定提供程序和连接字符串创建 Session 55 | /// 56 | /// 57 | /// 58 | /// 59 | public static ISession CreateSession( string providerName, string connectionStr ) 60 | { 61 | ISessionProviderFactory factory = SessionProviderFactories.GetFactory( providerName ); 62 | 63 | return factory.CreateSession( connectionStr ); 64 | } 65 | 66 | #endregion 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data/SessionProviderFactories.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Restful.Data 7 | { 8 | public class SessionProviderFactories 9 | { 10 | #region Member 11 | 12 | /// 13 | /// 存储已注册的 Session 工厂 14 | /// 15 | private static IDictionary factories = new Dictionary(); 16 | 17 | #endregion 18 | 19 | #region Register 20 | 21 | /// 22 | /// 注册 Session 工厂 23 | /// 24 | /// 25 | /// 26 | public static void Register() where T : ISessionProviderFactory 27 | { 28 | string providerName = typeof( T ).Assembly.GetName().Name; 29 | 30 | if( factories.ContainsKey( providerName ) ) 31 | { 32 | return; 33 | } 34 | 35 | T factory = Activator.CreateInstance(); 36 | 37 | factories.Add( providerName, factory ); 38 | } 39 | 40 | #endregion 41 | 42 | #region GetFactory 43 | 44 | /// 45 | /// 根据指定提供程序的 Session 工厂 46 | /// 47 | /// 48 | /// 49 | public static ISessionProviderFactory GetFactory( string providerName ) 50 | { 51 | if( factories.ContainsKey( providerName ) == false ) 52 | { 53 | throw new ArgumentException( string.Format( "提供程序 {0} 未注册。", providerName ), "providerName" ); 54 | } 55 | 56 | return factories[providerName]; 57 | } 58 | 59 | #endregion 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/Restful/Restful.Data/SqlCommandBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Restful.Data 5 | { 6 | public class SqlCommandBuilder : CommandBuilder 7 | { 8 | #region implemented abstract members of CommandBuilder 9 | 10 | public override string AddParameter( object value ) 11 | { 12 | throw new NotImplementedException(); 13 | } 14 | 15 | #endregion 16 | 17 | private string sql; 18 | 19 | #region implemented abstract members of CommandBuilder 20 | 21 | public override string Sql 22 | { 23 | get 24 | { 25 | return this.sql; 26 | } 27 | set 28 | { 29 | this.sql = value; 30 | } 31 | } 32 | 33 | #endregion 34 | 35 | private SqlCommandBuilder() : base() 36 | { 37 | } 38 | 39 | private SqlCommandBuilder( string sql ) : this() 40 | { 41 | this.sql = sql; 42 | } 43 | 44 | private SqlCommandBuilder( string sql, IDictionary parameters ) : this( sql ) 45 | { 46 | foreach( var item in parameters ) 47 | { 48 | this.AddParameter( item.Key, item.Value ); 49 | } 50 | } 51 | } 52 | } 53 | 54 | -------------------------------------------------------------------------------- /src/Restful/Restful.Linq/Extensions/IDeleteableExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | using System.Linq; 4 | using Restful; 5 | 6 | namespace Restful.Linq 7 | { 8 | public static class IDeleteableExtensions 9 | { 10 | /// 11 | /// 设置筛选函数 12 | /// 13 | /// IDeleteable 对象 14 | /// 用于测试每个源元素是否满足条件的函数 15 | public static IDeleteable Where( this IDeleteable source, Expression predicate ) 16 | { 17 | if( predicate == null ) 18 | return source; 19 | 20 | if( source.Predicate == null ) 21 | { 22 | source.Predicate = predicate; 23 | } 24 | else 25 | { 26 | source.Predicate = Expression.AndAlso( source.Predicate, predicate ); 27 | } 28 | 29 | return source; 30 | } 31 | 32 | /// 33 | /// 执行删除操作 34 | /// 35 | /// IDeleteable 对象 36 | /// 元素类型 37 | public static int Execute( this IDeleteable source, Type elementType ) 38 | { 39 | return source.Provider.Execute( elementType, source.Predicate ); 40 | } 41 | } 42 | } 43 | 44 | -------------------------------------------------------------------------------- /src/Restful/Restful.Linq/Extensions/IDeleteableGenericExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | 4 | namespace Restful.Linq 5 | { 6 | public static class IDeleteableGenericExtensions 7 | { 8 | /// 9 | /// 设置筛选函数 10 | /// 11 | /// IDeleteable 对象 12 | /// 用于测试每个源元素是否满足条件的函数 13 | /// The 1st type parameter. 14 | public static IDeleteable Where( this IDeleteable source, Expression> predicate ) 15 | { 16 | if( predicate == null ) 17 | return source; 18 | 19 | if( source.Predicate == null ) 20 | { 21 | source.Predicate = predicate.Body; 22 | } 23 | else 24 | { 25 | source.Predicate = Expression.AndAlso( source.Predicate, predicate.Body ); 26 | } 27 | 28 | return source; 29 | } 30 | 31 | /// 32 | /// 执行删除操作 33 | /// 34 | /// IDeleteable 对象 35 | /// 元素类型 36 | public static int Execute( this IDeleteable source ) 37 | { 38 | return source.Provider.Execute( source.Predicate ); 39 | } 40 | } 41 | } 42 | 43 | -------------------------------------------------------------------------------- /src/Restful/Restful.Linq/Extensions/IInsertableExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | using System.Linq; 4 | using Restful; 5 | 6 | namespace Restful.Linq 7 | { 8 | public static class IInsertableExtensions 9 | { 10 | /// 11 | /// 设置需新增的字段和值 12 | /// 13 | /// source 14 | /// 字段 15 | /// 值 16 | public static IInsertable Set( this IInsertable source, MemberExpression property, object value ) 17 | { 18 | var key = source.Properties.Keys.Where( s => s.MemberExpressionEqual( property ) ).FirstOrDefault(); 19 | 20 | if( key == null ) 21 | { 22 | source.Properties.Add( property, value ); 23 | } 24 | else 25 | { 26 | source.Properties[key] = value; 27 | } 28 | 29 | return source; 30 | } 31 | 32 | /// 33 | /// 执行未指定元素类型的插入操作 34 | /// 35 | /// Source. 36 | /// Element type. 37 | public static int Execute( this IInsertable source, Type elementType ) 38 | { 39 | return source.Provider.Execute( elementType, source.Properties ); 40 | } 41 | } 42 | } 43 | 44 | -------------------------------------------------------------------------------- /src/Restful/Restful.Linq/Extensions/IInsertableGenericExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Linq.Expressions; 4 | 5 | namespace Restful.Linq 6 | { 7 | public static class IInsertableGenericExtensions 8 | { 9 | /// 10 | /// 设置需新增的字段和值 11 | /// 12 | /// 13 | /// 字段 14 | /// 值 15 | /// 元素类型 16 | public static IInsertable Set( this IInsertable source, Expression> property, object value ) 17 | { 18 | MemberExpression me = property.Body.ToMemberExpression(); 19 | 20 | var key = source.Properties.Keys.Where( s => s.MemberExpressionEqual( me ) ).FirstOrDefault(); 21 | 22 | if( key == null ) 23 | { 24 | source.Properties.Add( me, value ); 25 | } 26 | else 27 | { 28 | source.Properties[key] = value; 29 | } 30 | 31 | return source; 32 | } 33 | 34 | /// 35 | /// 执行指定类型元素的删除操作 36 | /// 37 | /// 可新增的对象 38 | /// 受影响的行数 39 | public static int Execute( this IInsertable source ) 40 | { 41 | return source.Provider.Execute( source.Properties ); 42 | } 43 | } 44 | } 45 | 46 | -------------------------------------------------------------------------------- /src/Restful/Restful.Linq/Extensions/IUpdateableExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | using System.Linq; 4 | using Restful; 5 | 6 | namespace Restful.Linq 7 | { 8 | public static class IUpdateableExtensions 9 | { 10 | public static IUpdateable Set( this IUpdateable source, MemberExpression me, object value ) 11 | { 12 | var key = source.Properties.Keys.Where( s => s.MemberExpressionEqual( me ) ).FirstOrDefault(); 13 | 14 | if( key == null ) 15 | { 16 | source.Properties.Add( me, value ); 17 | } 18 | else 19 | { 20 | source.Properties[key] = value; 21 | } 22 | 23 | return source; 24 | } 25 | 26 | public static IUpdateable Where( this IUpdateable source, Expression predicate ) 27 | { 28 | if( predicate == null ) 29 | return source; 30 | 31 | if( source.Predicate == null ) 32 | { 33 | source.Predicate = predicate; 34 | } 35 | else 36 | { 37 | source.Predicate = Expression.AndAlso( source.Predicate, predicate ); 38 | } 39 | 40 | return source; 41 | } 42 | 43 | public static int Execute( this IUpdateable source, Type elementType ) 44 | { 45 | return source.Provider.Execute( elementType, source.Properties, source.Predicate ); 46 | } 47 | } 48 | } 49 | 50 | -------------------------------------------------------------------------------- /src/Restful/Restful.Linq/Extensions/IUpdateableGenericExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Linq.Expressions; 4 | 5 | namespace Restful.Linq 6 | { 7 | public static class IUpdateableGenericExtensions 8 | { 9 | /// 10 | /// 设置需更新的字段和值 11 | /// 12 | /// source 13 | /// 字段 14 | /// 值 15 | /// 元素类型 16 | public static IUpdateable Set( this IUpdateable source, Expression> property, object value ) 17 | { 18 | MemberExpression me = property.Body.ToMemberExpression(); 19 | 20 | var key = source.Properties.Keys.Where( s => s.MemberExpressionEqual( me ) ).FirstOrDefault(); 21 | 22 | if( key == null ) 23 | { 24 | source.Properties.Add( me, value ); 25 | } 26 | else 27 | { 28 | source.Properties[key] = value; 29 | } 30 | 31 | return source; 32 | } 33 | 34 | /// 35 | /// 设置过滤函数 36 | /// 37 | /// source 38 | /// 过滤函数 39 | /// 元素类型 40 | public static IUpdateable Where( this IUpdateable source, Expression> predicate ) 41 | { 42 | if( predicate == null ) 43 | return source; 44 | 45 | if( source.Predicate == null ) 46 | { 47 | source.Predicate = predicate.Body; 48 | } 49 | else 50 | { 51 | source.Predicate = Expression.AndAlso( source.Predicate, predicate.Body ); 52 | } 53 | 54 | return source; 55 | } 56 | 57 | /// 58 | /// 执行指定元素类型的更新操作 59 | /// 60 | /// source 61 | /// 元素类型 62 | public static int Execute( this IUpdateable source ) 63 | { 64 | return source.Provider.Execute( source.Properties, source.Predicate ); 65 | } 66 | } 67 | } 68 | 69 | -------------------------------------------------------------------------------- /src/Restful/Restful.Linq/IDeleteProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | 4 | namespace Restful.Linq 5 | { 6 | /// 7 | /// 定义用于创建和执行 IDeleteable 对象所描述的删除的方法。 8 | /// 9 | public interface IDeleteProvider 10 | { 11 | #region IDeleteable Support 12 | 13 | /// 14 | /// 构造一个 IDeleteable 对象,该对象可计算指定表达式树所表示的删除。 15 | /// 16 | /// 一个 IDeleteable,它可计算指定表达式树所表示的删除。 17 | /// 元素类型 18 | IDeleteable CreateDelete( Type elementType ); 19 | 20 | /// 21 | /// 执行删除操作。 22 | /// 23 | /// 元素类型 24 | /// where 表达式树 25 | int Execute( Type elementType, Expression predicate ); 26 | 27 | #endregion 28 | 29 | #region IDeleteable Support 30 | 31 | /// 32 | /// 构造一个 IDeleteable 对象,该对象可计算指定表达式树所表示的删除。 33 | /// 34 | /// 一个 IDeleteable,它可计算指定表达式树所表示的删除。 35 | /// 需删除的元素类型 36 | IDeleteable CreateDelete(); 37 | 38 | /// 39 | /// 执行删除操作。 40 | /// 41 | /// where 表达式树 42 | int Execute( Expression predicate ); 43 | 44 | #endregion 45 | } 46 | } 47 | 48 | -------------------------------------------------------------------------------- /src/Restful/Restful.Linq/IDeleteable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Linq.Expressions; 4 | 5 | namespace Restful.Linq 6 | { 7 | /// 8 | /// 提供对未指定数据类型的特定数据源的删除进行计算的功能。 9 | /// 10 | public interface IDeleteable 11 | { 12 | /// 13 | /// 获取元素类型 14 | /// 15 | Type ElementType { get; } 16 | 17 | /// 18 | /// 获取过滤表达式树 19 | /// 20 | Expression Predicate { get; set; } 21 | 22 | /// 23 | /// 获取与此数据源关联的删除提供程序。 24 | /// 25 | IDeleteProvider Provider { get; } 26 | } 27 | 28 | /// 29 | /// 提供对数据类型已知的特定数据源的删除进行计算的功能。 30 | /// 31 | public interface IDeleteable : IDeleteable 32 | { 33 | 34 | } 35 | } 36 | 37 | -------------------------------------------------------------------------------- /src/Restful/Restful.Linq/IInsertProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | using System.Collections.Generic; 4 | 5 | namespace Restful.Linq 6 | { 7 | /// 8 | /// 定义用于创建和执行 IInsertable 对象所描述的插入的方法。 9 | /// 10 | public interface IInsertProvider 11 | { 12 | /// 13 | /// 构造一个 IInsertable 对象,该对象可计算指定表达式树所表示的插入。 14 | /// 15 | /// 一个 IInsertable,它可计算指定表达式树所表示的插入。 16 | IInsertable CreateInsert( Type elementType ); 17 | 18 | /// 19 | /// 构造一个 IInsertable 对象,该对象可计算指定表达式树所表示的插入。 20 | /// 21 | /// 一个 IInsertable,它可计算指定表达式树所表示的插入。 22 | /// 需插入的元素类型 23 | IInsertable CreateInsert(); 24 | 25 | /// 26 | /// 执行删除操作。 27 | /// 28 | /// 元素类型 29 | /// where 表达式树 30 | int Execute( Type elementType, IDictionary properties ); 31 | 32 | /// 33 | /// 执行插入操作。 34 | /// 35 | /// 插入时需设置的属性集合 36 | int Execute( IDictionary properties ); 37 | } 38 | } 39 | 40 | -------------------------------------------------------------------------------- /src/Restful/Restful.Linq/IInsertable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq.Expressions; 4 | 5 | namespace Restful.Linq 6 | { 7 | /// 8 | /// 提供对未指定数据类型的特定数据源的插入进行计算的功能。 9 | /// 10 | public interface IInsertable 11 | { 12 | /// 13 | /// 获取插入时需设置的属性集合 14 | /// 15 | IDictionary Properties { get; } 16 | 17 | /// 18 | /// 获取与此数据源关联的更新提供程序。 19 | /// 20 | IInsertProvider Provider { get; } 21 | } 22 | 23 | /// 24 | /// 提供对数据类型已知的特定数据源的插入进行计算的功能。 25 | /// 26 | public interface IInsertable : IInsertable 27 | { 28 | } 29 | } 30 | 31 | -------------------------------------------------------------------------------- /src/Restful/Restful.Linq/IUpdateProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | using System.Collections.Generic; 4 | 5 | namespace Restful.Linq 6 | { 7 | /// 8 | /// 定义用于创建和执行 IUpdateable 对象所描述的更新的方法。 9 | /// 10 | public interface IUpdateProvider 11 | { 12 | /// 13 | /// 构造一个 IUpdateable 对象,该对象可计算指定表达式树所表示的更新。 14 | /// 15 | /// 一个 IUpdateable,它可计算指定表达式树所表示的更新。 16 | IUpdateable CreateUpdate( Type elementType ); 17 | 18 | /// 19 | /// 构造一个 IUpdateable 对象,该对象可计算指定表达式树所表示的更新。 20 | /// 21 | /// 一个 IUpdateable,它可计算指定表达式树所表示的更新。 22 | /// 需更新的元素类型 23 | IUpdateable CreateUpdate(); 24 | 25 | /// 26 | /// 执行更新操作。 27 | /// 28 | /// 更新时需设置的属性集合 29 | /// where 表达式树 30 | int Execute( Type elementType, IDictionary properties, Expression predicate ); 31 | 32 | /// 33 | /// 执行更新操作。 34 | /// 35 | /// 更新时需设置的属性集合 36 | /// where 表达式树 37 | int Execute( IDictionary properties, Expression predicate ); 38 | } 39 | } 40 | 41 | -------------------------------------------------------------------------------- /src/Restful/Restful.Linq/IUpdateable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | using System.Collections; 4 | using System.Collections.Generic; 5 | 6 | namespace Restful.Linq 7 | { 8 | /// 9 | /// 提供对未指定数据类型的特定数据源的更新进行计算的功能。 10 | /// 11 | public interface IUpdateable 12 | { 13 | /// 14 | /// 获取更新时需设置的属性集合 15 | /// 16 | IDictionary Properties { get; } 17 | 18 | /// 19 | /// 获取过滤表达式树 20 | /// 21 | Expression Predicate { get; set; } 22 | 23 | /// 24 | /// 获取与此数据源关联的更新提供程序。 25 | /// 26 | IUpdateProvider Provider { get; } 27 | } 28 | 29 | /// 30 | /// 提供对数据类型已知的特定数据源的更新进行计算的功能。 31 | /// 32 | public interface IUpdateable : IUpdateable 33 | { 34 | } 35 | } 36 | 37 | -------------------------------------------------------------------------------- /src/Restful/Restful.Linq/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | 4 | // Information about this assembly is defined by the following attributes. 5 | // Change them to the values specific to your project. 6 | 7 | [assembly: AssemblyTitle( "Restful.Linq" )] 8 | [assembly: AssemblyDescription( "" )] 9 | [assembly: AssemblyConfiguration( "" )] 10 | [assembly: AssemblyCompany( "" )] 11 | [assembly: AssemblyProduct( "" )] 12 | [assembly: AssemblyCopyright( "zhaogh" )] 13 | [assembly: AssemblyTrademark( "" )] 14 | [assembly: AssemblyCulture( "" )] 15 | 16 | // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". 17 | // The form "{Major}.{Minor}.*" will automatically update the build and revision, 18 | // and "{Major}.{Minor}.{Build}.*" will update just the revision. 19 | 20 | [assembly: AssemblyVersion( "1.0.*" )] 21 | 22 | // The following attributes are used to specify the signing key for the assembly, 23 | // if desired. See the Mono documentation for more information about signing. 24 | 25 | //[assembly: AssemblyDelaySign(false)] 26 | //[assembly: AssemblyKeyFile("")] 27 | 28 | -------------------------------------------------------------------------------- /src/Restful/Restful.Linq/Restful.Linq.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | {39D214BE-3A4A-4174-8C53-5B7B5654D1AA} 7 | Library 8 | Restful.Linq 9 | Restful.Linq 10 | 2.0 11 | 12 | 13 | true 14 | full 15 | false 16 | ..\..\..\lib 17 | DEBUG; 18 | prompt 19 | 4 20 | false 21 | 22 | 23 | full 24 | true 25 | ..\..\..\lib 26 | prompt 27 | 4 28 | false 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | {ECEDCBF3-7039-4A01-B87A-DA84DA939404} 52 | Restful 53 | 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /src/Restful/Restful.NUnitTests/Restful.NUnitTests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | {11E5DAF2-F969-42E1-8C4F-4156A0856F02} 7 | Library 8 | Restful.NUnitTests 9 | Restful.NUnitTests 10 | 2.0 11 | 12 | 13 | true 14 | full 15 | false 16 | bin\Debug 17 | DEBUG; 18 | prompt 19 | 4 20 | false 21 | 22 | 23 | full 24 | true 25 | bin\Release 26 | prompt 27 | 4 28 | false 29 | AnyCPU 30 | 31 | 32 | 33 | 34 | 35 | 36 | ..\References\nunit.framework.dll 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | {39D214BE-3A4A-4174-8C53-5B7B5654D1AA} 48 | Restful.Linq 49 | 50 | 51 | {ECEDCBF3-7039-4A01-B87A-DA84DA939404} 52 | Restful 53 | 54 | 55 | {4BA05EF7-5312-4B37-B0A2-07E68DD05BEA} 56 | Restful.Data 57 | 58 | 59 | {C0CF8F4F-8D96-43C8-92A2-35029C643A84} 60 | Restful.Data.MySql 61 | 62 | 63 | {D42F1E6A-CD91-49CE-B3D0-95906C62C471} 64 | Restful.Data.Oracle 65 | 66 | 67 | {E421F9CE-9BD9-4A85-8CF4-4919B013063E} 68 | Restful.Data.SqlServer 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /src/Restful/Restful.NUnitTests/app.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/Restful/Restful.NUnitTests/bin/Release/Castle.Core.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linli8/Restful/16013bf91d508b88e3819e533b8517a6483075b2/src/Restful/Restful.NUnitTests/bin/Release/Castle.Core.dll -------------------------------------------------------------------------------- /src/Restful/Restful.NUnitTests/bin/Release/MySql.Data.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linli8/Restful/16013bf91d508b88e3819e533b8517a6483075b2/src/Restful/Restful.NUnitTests/bin/Release/MySql.Data.dll -------------------------------------------------------------------------------- /src/Restful/Restful.NUnitTests/bin/Release/Oracle.DataAccess.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linli8/Restful/16013bf91d508b88e3819e533b8517a6483075b2/src/Restful/Restful.NUnitTests/bin/Release/Oracle.DataAccess.dll -------------------------------------------------------------------------------- /src/Restful/Restful.NUnitTests/bin/Release/Remotion.Linq.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linli8/Restful/16013bf91d508b88e3819e533b8517a6483075b2/src/Restful/Restful.NUnitTests/bin/Release/Remotion.Linq.dll -------------------------------------------------------------------------------- /src/Restful/Restful.NUnitTests/bin/Release/Restful.Data.MySql.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linli8/Restful/16013bf91d508b88e3819e533b8517a6483075b2/src/Restful/Restful.NUnitTests/bin/Release/Restful.Data.MySql.dll -------------------------------------------------------------------------------- /src/Restful/Restful.NUnitTests/bin/Release/Restful.Data.Oracle.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linli8/Restful/16013bf91d508b88e3819e533b8517a6483075b2/src/Restful/Restful.NUnitTests/bin/Release/Restful.Data.Oracle.dll -------------------------------------------------------------------------------- /src/Restful/Restful.NUnitTests/bin/Release/Restful.Data.SqlServer.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linli8/Restful/16013bf91d508b88e3819e533b8517a6483075b2/src/Restful/Restful.NUnitTests/bin/Release/Restful.Data.SqlServer.dll -------------------------------------------------------------------------------- /src/Restful/Restful.NUnitTests/bin/Release/Restful.Data.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linli8/Restful/16013bf91d508b88e3819e533b8517a6483075b2/src/Restful/Restful.NUnitTests/bin/Release/Restful.Data.dll -------------------------------------------------------------------------------- /src/Restful/Restful.NUnitTests/bin/Release/Restful.Linq.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linli8/Restful/16013bf91d508b88e3819e533b8517a6483075b2/src/Restful/Restful.NUnitTests/bin/Release/Restful.Linq.dll -------------------------------------------------------------------------------- /src/Restful/Restful.NUnitTests/bin/Release/Restful.NUnitTests.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linli8/Restful/16013bf91d508b88e3819e533b8517a6483075b2/src/Restful/Restful.NUnitTests/bin/Release/Restful.NUnitTests.dll -------------------------------------------------------------------------------- /src/Restful/Restful.NUnitTests/bin/Release/Restful.NUnitTests.dll.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/Restful/Restful.NUnitTests/bin/Release/Restful.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linli8/Restful/16013bf91d508b88e3819e533b8517a6483075b2/src/Restful/Restful.NUnitTests/bin/Release/Restful.dll -------------------------------------------------------------------------------- /src/Restful/Restful.NUnitTests/bin/Release/nunit.framework.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linli8/Restful/16013bf91d508b88e3819e533b8517a6483075b2/src/Restful/Restful.NUnitTests/bin/Release/nunit.framework.dll -------------------------------------------------------------------------------- /src/Restful/Restful.userprefs: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/Restful/Restful/Extensions/ExpressionExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | 4 | namespace System.Linq.Expressions 5 | { 6 | public static class ExpressionExtensions 7 | { 8 | #region IsConstantNull 9 | 10 | /// 11 | /// 指示表达式是否为常量 null 12 | /// 13 | /// 表达式 14 | /// 15 | public static bool IsConstantNull( this Expression expression ) 16 | { 17 | return ( ( expression is ConstantExpression ) && ( (ConstantExpression)expression ).Value == null ); 18 | } 19 | 20 | #endregion 21 | 22 | #region ToMemberExpression 23 | 24 | /// 25 | /// 将表达式转换为 MemberExpression 26 | /// 27 | /// The to member expression. 28 | /// Expression. 29 | public static MemberExpression ToMemberExpression( this Expression expression ) 30 | { 31 | switch( expression.NodeType ) 32 | { 33 | case ExpressionType.MemberAccess: 34 | return (MemberExpression)expression; 35 | case ExpressionType.Lambda: 36 | return ( (LambdaExpression)expression ).Body.ToMemberExpression(); 37 | case ExpressionType.Convert: 38 | return ( (UnaryExpression)expression ).Operand.ToMemberExpression(); 39 | default: 40 | throw new NotImplementedException( expression.NodeType.ToString() ); 41 | } 42 | } 43 | 44 | #endregion 45 | 46 | #region MemberExpressionEqual 47 | 48 | /// 49 | /// 判断两个 MemberExpression 是否相同 50 | /// 51 | /// true, if expression equal was membered, false otherwise. 52 | /// The x coordinate. 53 | /// The y coordinate. 54 | public static bool MemberExpressionEqual( this MemberExpression x, MemberExpression y ) 55 | { 56 | if( ReferenceEquals( x, y ) ) 57 | return true; 58 | 59 | if( x == null || y == null ) 60 | return false; 61 | 62 | if( x.NodeType != y.NodeType || x.Type != y.Type ) 63 | return false; 64 | 65 | return x.Member == y.Member; 66 | } 67 | 68 | #endregion 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/Restful/Restful/Extensions/IEnumerableGenericExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace System.Collections.Generic 4 | { 5 | public static class IEnumerableGenericExtensions 6 | { 7 | #region Each 8 | 9 | /// 10 | /// 遍历 IEnumerable 对象,并执行操作 11 | /// 12 | /// 13 | /// 14 | /// 15 | public static void Each( this IEnumerable enumerable, Action action ) 16 | { 17 | foreach( var item in enumerable ) 18 | { 19 | action( item ); 20 | } 21 | } 22 | 23 | #endregion 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Restful/Restful/Extensions/ObjectExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace System 4 | { 5 | public static class ObjectExtensions 6 | { 7 | #region Cast 8 | 9 | /// 10 | /// 将对象转换为指定类型的对象 11 | /// 12 | /// 原对象 13 | /// 目标类型 14 | /// 转换后的对象 15 | public static object Cast( this object @object, Type targetType ) 16 | { 17 | if( ( @object == null ) || ( @object.GetType() == typeof( DBNull ) ) ) 18 | { 19 | return null; 20 | } 21 | 22 | if( targetType.IsGenericType && targetType.GetGenericTypeDefinition().Equals( typeof( Nullable<> ) ) ) 23 | { 24 | targetType = Nullable.GetUnderlyingType( targetType ); 25 | } 26 | 27 | return Convert.ChangeType( @object, targetType ); 28 | } 29 | 30 | #endregion 31 | 32 | #region Cast 33 | 34 | /// 35 | /// 将对象转换成指定对象 36 | /// 37 | /// 目标类型 38 | /// 原对象 39 | /// 转换后的对象 40 | public static T Cast( this object @object ) 41 | { 42 | return (T)@object.Cast( typeof( T ) ); 43 | } 44 | 45 | #endregion 46 | 47 | #region IsNullOrEmpty 48 | 49 | /// 50 | /// 判断对象是否为空对象、空字符串、DBNull 51 | /// 52 | /// 53 | /// 54 | public static bool IsNullOrEmpty( this object @object ) 55 | { 56 | if( @object == null ) 57 | { 58 | return true; 59 | } 60 | 61 | if( @object is string ) 62 | { 63 | return string.IsNullOrEmpty( @object.ToString() ); 64 | } 65 | 66 | if( @object is DBNull ) 67 | { 68 | return @object == DBNull.Value; 69 | } 70 | 71 | return false; 72 | } 73 | 74 | #endregion 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/Restful/Restful/Extensions/PropertyInfoExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using Restful.Reflection.Emit; 3 | 4 | namespace System.Reflection 5 | { 6 | public static class PropertyInfoExtensions 7 | { 8 | /// 9 | /// 使用 Emit 方式获取属性值 10 | /// 11 | /// 12 | /// 13 | /// 14 | public static object EmitGetValue( this PropertyInfo property, object instance ) 15 | { 16 | DynamicPropertyGetHandler handler = DynamicHelper.CreateDynamicPropertyGetHandler( property ); 17 | 18 | return handler( instance ); 19 | } 20 | 21 | /// 22 | /// 通过 Emit 方式设置属性值 23 | /// 24 | /// 25 | /// 26 | /// 27 | public static void EmitSetValue( this PropertyInfo property, object instance, object value ) 28 | { 29 | DynamicPropertySetHandler handler = DynamicHelper.CreateDynamicPropertySetHandler( property ); 30 | 31 | handler( instance, value ); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Restful/Restful/Extensions/StringExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | 3 | namespace System 4 | { 5 | public static class StringExtensions 6 | { 7 | #region SplitPascalCase 8 | 9 | /// 10 | /// 将符合Pascal命名标准的字符串分割为多个单词 11 | /// 12 | /// 13 | /// 14 | public static string SplitPascalCase( this string @object ) 15 | { 16 | if( string.IsNullOrEmpty( @object ) ) 17 | return @object; 18 | 19 | if( @object.ToUpper() == "ID" ) 20 | return @object; 21 | 22 | return Regex.Replace( @object, "([A-Z])", " $1", RegexOptions.Compiled ).Trim(); 23 | } 24 | 25 | #endregion 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Restful/Restful/Extensions/TypeExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq.Expressions; 4 | 5 | namespace Restful 6 | { 7 | public static class TypeExtensions 8 | { 9 | /// 10 | /// 判断类型是否为匿名类型 11 | /// 12 | /// 13 | /// 14 | public static bool IsAnonymousType( this Type @type ) 15 | { 16 | return @type.Namespace == null; 17 | } 18 | 19 | public static Type GetElementType( this Type seqType ) 20 | { 21 | Type ienum = seqType.FindIEnumerable(); 22 | 23 | if( ienum == null ) 24 | return seqType; 25 | 26 | return ienum.GetGenericArguments()[0]; 27 | } 28 | 29 | public static Type FindIEnumerable( this Type seqType ) 30 | { 31 | if( seqType == null || seqType == typeof( string ) ) 32 | return null; 33 | 34 | if( seqType.IsArray ) 35 | { 36 | return typeof( IEnumerable<> ).MakeGenericType( seqType.GetElementType() ); 37 | } 38 | 39 | if( seqType.IsGenericType ) 40 | { 41 | foreach( Type arg in seqType.GetGenericArguments() ) 42 | { 43 | Type ienum = typeof( IEnumerable<> ).MakeGenericType( arg ); 44 | 45 | if( ienum.IsAssignableFrom( seqType ) ) 46 | { 47 | return ienum; 48 | } 49 | } 50 | } 51 | 52 | Type[] ifaces = seqType.GetInterfaces(); 53 | 54 | if( ifaces != null && ifaces.Length > 0 ) 55 | { 56 | foreach( Type iface in ifaces ) 57 | { 58 | Type ienum = FindIEnumerable( iface ); 59 | 60 | if( ienum != null ) 61 | return ienum; 62 | } 63 | } 64 | 65 | if( seqType.BaseType != null && seqType.BaseType != typeof( object ) ) 66 | { 67 | return FindIEnumerable( seqType.BaseType ); 68 | } 69 | 70 | return null; 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/Restful/Restful/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的常规信息通过以下 6 | // 特性集控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle("Restful")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Restful")] 13 | [assembly: AssemblyCopyright("Copyright © 2014")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // 将 ComVisible 设置为 false 使此程序集中的类型 18 | // 对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型, 19 | // 则将该类型上的 ComVisible 特性设置为 true。 20 | [assembly: ComVisible(false)] 21 | 22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 23 | [assembly: Guid("1d209149-4814-4cdf-ae8f-bc6d985f29f2")] 24 | 25 | // 程序集的版本信息由下面四个值组成: 26 | // 27 | // 主版本 28 | // 次版本 29 | // 生成号 30 | // 修订号 31 | // 32 | // 可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值, 33 | // 方法是按如下所示使用“*”: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/Restful/Restful/Restful.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {ECEDCBF3-7039-4A01-B87A-DA84DA939404} 8 | Library 9 | Properties 10 | Restful 11 | Restful 12 | v4.0 13 | 512 14 | 15 | 2.0 16 | 17 | 18 | true 19 | full 20 | false 21 | ..\..\..\lib 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | pdbonly 28 | true 29 | ..\..\..\lib 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /src/Restful/实体生成器模板.cmt: -------------------------------------------------------------------------------- 1 | <#@ template language="c#" HostSpecific="True" #> 2 | <#@ output extension= ".cs" #> 3 | <# 4 | TableHost host = (TableHost)(Host); 5 | host.Fieldlist.Sort(CodeCommon.CompareByintOrder); 6 | #> 7 | using System; 8 | using System.Text; 9 | using System.Collections.Generic; 10 | using System.Data; 11 | using Restful.Data.Attributes; 12 | 13 | namespace Entities 14 | { 15 | <# if( host.TableDescription.Length > 0) {#> 16 | //<#= host.TableDescription #> 17 | <# } #> 18 | public class <#= host.TableName #> 19 | { 20 | <# foreach (ColumnInfo c in host.Fieldlist) 21 | { 22 | WriteLine("///"); 23 | WriteLine("///{0}",c.ColumnName); 24 | WriteLine("///"); 25 | WriteLine("public virtual {0} {1} {{ get; set; }}",CodeCommon.DbTypeToCS(c.TypeName),c.ColumnName ); 26 | } #> 27 | } 28 | } --------------------------------------------------------------------------------