diff --git a/ams/Djy.Common/DapperDBBase.cs b/ams/Djy.Common/DapperDBBase.cs
index 6e5b029..9fc1df6 100644
--- a/ams/Djy.Common/DapperDBBase.cs
+++ b/ams/Djy.Common/DapperDBBase.cs
@@ -6,35 +6,32 @@ using Microsoft.Extensions.Configuration;
using System.Collections.Generic;
using System.Data;
using System.Threading.Tasks;
+using Common;
+using Microsoft.EntityFrameworkCore;
namespace Shared.Repository
{
///
/// Dapper帮助类
///
- public sealed class DapperDBBase : IDapperDBBase
+ public class DapperDBBase : DbContext, IDapperDBBase
{
private string sqlConnection;
- private readonly IConfiguration _configuration;
- ///
- ///
- ///
- ///
- public DapperDBBase(IConfiguration configuration)
+
+ public DapperDBBase()
{
- _configuration = configuration;
- sqlConnection = configuration.GetConnectionString("OpenAuthDBContext");
+ sqlConnection = sysOptionConfig.YsWebconfig.DapperDbString;
}
-
///
///
///
///
- public IDbConnection GetConn()
+ public IDbConnection GetConn(string type = null)
{
if (string.IsNullOrEmpty(sqlConnection))
- sqlConnection = _configuration.GetConnectionString("OpenAuthDBContext");
+
+ sqlConnection = sysOptionConfig.YsWebconfig.DapperDbString;
IDbConnection conn = new SqlConnection(sqlConnection);
conn.Open();
return conn;
@@ -470,29 +467,78 @@ namespace Shared.Repository
}
return iResult;
}
- //以下为使用方法
- //public async Task GetUserDetailAsync(int Id)
- //{
- // string detailSql = @"SELECT ID, UserName, Password, Gender, Birthday, CreateDate, IsDelete FROM [dbo].[Users] WHERE Id=@Id";
- // return await base.Detail(Id, detailSql);
- //}
-
- //public async Task> GetUsersAsync()
- //{
- // string selectSql = @"SELECT userName,Password,Gender ,Birthday ,CreateDate ,IsDelete FROM [dbo].[Users]";
- // return await base.Select(selectSql);
- //}
-
- //public async Task PostUserAsync(Users entity)
- //{
- // string insertSql = @"INSERT INTO [dbo].[Users](Id, UserName, Password, Gender, Birthday, CreateDate, IsDelete) VALUES(@Id, @UserName, @Password, @Gender, @Birthday, @CreateDate, @IsDelete)";
- // await base.Insert(entity, insertSql);
- //}
-
- //public async Task PutUserAsync(Users entity)
- //{
- // string updateSql = "UPDATE [dbo].[Users] SET UserName=@UserName, Password=@Password, Gender=@Gender, Birthday=@Birthday, CreateDate=@CreateDate, IsDelete=@IsDelete WHERE Id=@Id";
- // await base.Update(entity, updateSql);
- //}
+ ///
+ /// 开启事务
+ ///
+ ///
+ ///
+ public IDbTransaction BeginTransaction(IDbConnection conn)
+ {
+ IDbTransaction tran = conn.BeginTransaction();
+ return tran;
+ }
+
+ ///
+ /// 提交事务
+ ///
+ ///
+ ///
+ public void Commit(IDbTransaction tran, IDbConnection conn)
+ {
+ tran.Commit();
+ }
+
+ ///
+ /// 回滚事务
+ ///
+ ///
+ ///
+ public void Rollback(IDbTransaction tran, IDbConnection conn)
+ {
+ tran.Rollback();
+ }
+
+
+
+
+ /// 数据库连接名
+ private static string _connection = string.Empty;
+
+ /// 获取连接名
+ private static string Connection
+ {
+ get { return _connection; }
+ set { _connection = value; }
+ }
+
+
+
+ /// 定义一个标识确保线程同步
+ private static readonly object locker = new object();
+
+ private static DapperDBBase uniqueInstance;
+ ///
+ /// 获取实例,这里为单例模式,保证只存在一个实例
+ ///
+ ///
+ public static DapperDBBase GetInstance()
+ {
+ // 双重锁定实现单例模式,在外层加个判空条件主要是为了减少加锁、释放锁的不必要的损耗
+ if (uniqueInstance == null)
+ {
+ lock (locker)
+ {
+ if (uniqueInstance == null)
+ {
+ uniqueInstance = new DapperDBBase();
+ }
+ }
+ }
+ return uniqueInstance;
+ }
+
+
+
+
}
}
diff --git a/ams/Djy.Common/Entity/WebConfig.cs b/ams/Djy.Common/Entity/WebConfig.cs
index 24b3eda..8667b7e 100644
--- a/ams/Djy.Common/Entity/WebConfig.cs
+++ b/ams/Djy.Common/Entity/WebConfig.cs
@@ -112,6 +112,9 @@ namespace Common
///
public int ShopPower { get; set; } = 2;
+
+ public string DapperDbString { get; set; }
+
#region jwt认证配置
///
/// jwt发行者
diff --git a/ams/Djy.Common/Interface/DynamicQueryable.cs b/ams/Djy.Common/Interface/DynamicQueryable.cs
new file mode 100644
index 0000000..906de94
--- /dev/null
+++ b/ams/Djy.Common/Interface/DynamicQueryable.cs
@@ -0,0 +1,2342 @@
+//Copyright (C) Microsoft Corporation. All rights reserved.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Text;
+using System.Threading;
+
+namespace Infrastructure
+{
+ public static class DynamicQueryable
+ {
+ public static IQueryable Where(this IQueryable source, string predicate, params object[] values)
+ {
+ return (IQueryable)Where((IQueryable)source, predicate, values);
+ }
+
+ public static IQueryable Where(this IQueryable source, string predicate, params object[] values)
+ {
+ if (source == null) throw new ArgumentNullException("source");
+ if (predicate == null) throw new ArgumentNullException("predicate");
+ LambdaExpression lambda = DynamicExpression.ParseLambda(source.ElementType, typeof(bool), predicate, values);
+ return source.Provider.CreateQuery(
+ Expression.Call(
+ typeof(Queryable), "Where",
+ new Type[] { source.ElementType },
+ source.Expression, Expression.Quote(lambda)));
+ }
+
+ public static IQueryable Select(this IQueryable source, string selector, params object[] values)
+ {
+ if (source == null) throw new ArgumentNullException("source");
+ if (selector == null) throw new ArgumentNullException("selector");
+ LambdaExpression lambda = DynamicExpression.ParseLambda(source.ElementType, null, selector, values);
+ return source.Provider.CreateQuery(
+ Expression.Call(
+ typeof(Queryable), "Select",
+ new Type[] { source.ElementType, lambda.Body.Type },
+ source.Expression, Expression.Quote(lambda)));
+ }
+
+ public static IQueryable OrderBy(this IQueryable source, string ordering, params object[] values)
+ {
+ return (IQueryable)OrderBy((IQueryable)source, ordering, values);
+ }
+
+ public static IQueryable ThenBy(this IQueryable source, string ordering, params object[] values)
+ {
+ return (IQueryable)ThenBy((IQueryable)source, ordering, values);
+ }
+
+ public static IQueryable ThenBy(this IQueryable source, string ordering, params object[] values)
+ {
+ if (source == null) throw new ArgumentNullException("source");
+ if (ordering == null) throw new ArgumentNullException("ordering");
+ ParameterExpression[] parameters = new ParameterExpression[] {
+ Expression.Parameter(source.ElementType, "") };
+ ExpressionParser parser = new ExpressionParser(parameters, ordering, values);
+ IEnumerable orderings = parser.ParseOrdering();
+ Expression queryExpr = source.Expression;
+ string methodAsc = "ThenBy";
+ string methodDesc = "ThenByDescending";
+ foreach (DynamicOrdering o in orderings)
+ {
+ queryExpr = Expression.Call(
+ typeof(Queryable), o.Ascending ? methodAsc : methodDesc,
+ new Type[] { source.ElementType, o.Selector.Type },
+ queryExpr, Expression.Quote(Expression.Lambda(o.Selector, parameters)));
+
+ }
+ return source.Provider.CreateQuery(queryExpr);
+ }
+
+ public static IQueryable OrderBy(this IQueryable source, string ordering, params object[] values)
+ {
+ if (source == null) throw new ArgumentNullException("source");
+ if (ordering == null) throw new ArgumentNullException("ordering");
+ ParameterExpression[] parameters = new ParameterExpression[] {
+ Expression.Parameter(source.ElementType, "") };
+ ExpressionParser parser = new ExpressionParser(parameters, ordering, values);
+ IEnumerable orderings = parser.ParseOrdering();
+ Expression queryExpr = source.Expression;
+ string methodAsc = "OrderBy";
+ string methodDesc = "OrderByDescending";
+ foreach (DynamicOrdering o in orderings)
+ {
+ queryExpr = Expression.Call(
+ typeof(Queryable), o.Ascending ? methodAsc : methodDesc,
+ new Type[] { source.ElementType, o.Selector.Type },
+ queryExpr, Expression.Quote(Expression.Lambda(o.Selector, parameters)));
+ methodAsc = "ThenBy";
+ methodDesc = "ThenByDescending";
+ }
+ return source.Provider.CreateQuery(queryExpr);
+ }
+
+ public static IQueryable OrderBy(this IQueryable source, string propertyName, bool ascending)
+ where T : class
+ {
+ Type type = typeof(T);
+
+ PropertyInfo property = type.GetProperty(propertyName);
+ if (property == null)
+ throw new ArgumentException("propertyName", "Not Exist");
+
+ ParameterExpression param = Expression.Parameter(type, "p");
+ Expression propertyAccessExpression = Expression.MakeMemberAccess(param, property);
+ LambdaExpression orderByExpression = Expression.Lambda(propertyAccessExpression, param);
+
+ string methodName = ascending ? "OrderBy" : "OrderByDescending";
+
+ MethodCallExpression resultExp = Expression.Call(typeof(Queryable), methodName,
+ new Type[] { type, property.PropertyType }, source.Expression, Expression.Quote(orderByExpression));
+
+ return source.Provider.CreateQuery(resultExp);
+ }
+
+ public static IQueryable Take(this IQueryable source, int count)
+ {
+ if (source == null) throw new ArgumentNullException("source");
+ return source.Provider.CreateQuery(
+ Expression.Call(
+ typeof(Queryable), "Take",
+ new Type[] { source.ElementType },
+ source.Expression, Expression.Constant(count)));
+ }
+
+ public static IQueryable Skip(this IQueryable source, int count)
+ {
+ if (source == null) throw new ArgumentNullException("source");
+ return source.Provider.CreateQuery(
+ Expression.Call(
+ typeof(Queryable), "Skip",
+ new Type[] { source.ElementType },
+ source.Expression, Expression.Constant(count)));
+ }
+
+ public static IQueryable GroupBy(this IQueryable source, string keySelector, string elementSelector, params object[] values)
+ {
+ if (source == null) throw new ArgumentNullException("source");
+ if (keySelector == null) throw new ArgumentNullException("keySelector");
+ if (elementSelector == null) throw new ArgumentNullException("elementSelector");
+ LambdaExpression keyLambda = DynamicExpression.ParseLambda(source.ElementType, null, keySelector, values);
+ LambdaExpression elementLambda = DynamicExpression.ParseLambda(source.ElementType, null, elementSelector, values);
+ return source.Provider.CreateQuery(
+ Expression.Call(
+ typeof(Queryable), "GroupBy",
+ new Type[] { source.ElementType, keyLambda.Body.Type, elementLambda.Body.Type },
+ source.Expression, Expression.Quote(keyLambda), Expression.Quote(elementLambda)));
+ }
+
+ public static bool Any(this IQueryable source)
+ {
+ if (source == null) throw new ArgumentNullException("source");
+ return (bool)source.Provider.Execute(
+ Expression.Call(
+ typeof(Queryable), "Any",
+ new Type[] { source.ElementType }, source.Expression));
+ }
+
+ public static int Count(this IQueryable source)
+ {
+ if (source == null) throw new ArgumentNullException("source");
+ return (int)source.Provider.Execute(
+ Expression.Call(
+ typeof(Queryable), "Count",
+ new Type[] { source.ElementType }, source.Expression));
+ }
+ }
+
+ public abstract class DynamicClass
+ {
+ public override string ToString()
+ {
+ PropertyInfo[] props = this.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);
+ StringBuilder sb = new StringBuilder();
+ sb.Append("{");
+ for (int i = 0; i < props.Length; i++)
+ {
+ if (i > 0) sb.Append(", ");
+ sb.Append(props[i].Name);
+ sb.Append("=");
+ sb.Append(props[i].GetValue(this, null));
+ }
+ sb.Append("}");
+ return sb.ToString();
+ }
+ }
+
+ public class DynamicProperty
+ {
+ string name;
+ Type type;
+
+ public DynamicProperty(string name, Type type)
+ {
+ if (name == null) throw new ArgumentNullException("name");
+ if (type == null) throw new ArgumentNullException("type");
+ this.name = name;
+ this.type = type;
+ }
+
+ public string Name
+ {
+ get { return name; }
+ }
+
+ public Type Type
+ {
+ get { return type; }
+ }
+ }
+
+ public static class DynamicExpression
+ {
+ public static Expression Parse(Type resultType, string expression, params object[] values)
+ {
+ ExpressionParser parser = new ExpressionParser(null, expression, values);
+ return parser.Parse(resultType);
+ }
+
+ public static LambdaExpression ParseLambda(Type itType, Type resultType, string expression, params object[] values)
+ {
+ return ParseLambda(new ParameterExpression[] { Expression.Parameter(itType, "") }, resultType, expression, values);
+ }
+
+ public static LambdaExpression ParseLambda(ParameterExpression[] parameters, Type resultType, string expression, params object[] values)
+ {
+ ExpressionParser parser = new ExpressionParser(parameters, expression, values);
+ return Expression.Lambda(parser.Parse(resultType), parameters);
+ }
+
+ public static Expression> ParseLambda(string expression, params object[] values)
+ {
+ return (Expression>)ParseLambda(typeof(T), typeof(S), expression, values);
+ }
+
+ public static Type CreateClass(params DynamicProperty[] properties)
+ {
+ return ClassFactory.Instance.GetDynamicClass(properties);
+ }
+
+ public static Type CreateClass(IEnumerable properties)
+ {
+ return ClassFactory.Instance.GetDynamicClass(properties);
+ }
+ }
+
+ internal class DynamicOrdering
+ {
+ public Expression Selector;
+ public bool Ascending;
+ }
+
+ internal class Signature : IEquatable
+ {
+ public DynamicProperty[] properties;
+ public int hashCode;
+
+ public Signature(IEnumerable properties)
+ {
+ this.properties = properties.ToArray();
+ hashCode = 0;
+ foreach (DynamicProperty p in properties)
+ {
+ hashCode ^= p.Name.GetHashCode() ^ p.Type.GetHashCode();
+ }
+ }
+
+ public override int GetHashCode()
+ {
+ return hashCode;
+ }
+
+ public override bool Equals(object obj)
+ {
+ return obj is Signature ? Equals((Signature)obj) : false;
+ }
+
+ public bool Equals(Signature other)
+ {
+ if (properties.Length != other.properties.Length) return false;
+ for (int i = 0; i < properties.Length; i++)
+ {
+ if (properties[i].Name != other.properties[i].Name ||
+ properties[i].Type != other.properties[i].Type) return false;
+ }
+ return true;
+ }
+ }
+
+ internal class ClassFactory
+ {
+ public static readonly ClassFactory Instance = new ClassFactory();
+
+ static ClassFactory() { } // Trigger lazy initialization of static fields
+
+ ModuleBuilder module;
+ Dictionary classes;
+ int classCount;
+ ReaderWriterLock rwLock;
+
+ private ClassFactory()
+ {
+ AssemblyName name = new AssemblyName("DynamicClasses");
+ AssemblyBuilder assembly = AssemblyBuilder.DefineDynamicAssembly(name, AssemblyBuilderAccess.Run);
+ // AssemblyBuilder assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.Run);
+#if ENABLE_LINQ_PARTIAL_TRUST
+ new ReflectionPermission(PermissionState.Unrestricted).Assert();
+#endif
+ try
+ {
+ module = assembly.DefineDynamicModule("Module");
+ }
+ finally
+ {
+#if ENABLE_LINQ_PARTIAL_TRUST
+ PermissionSet.RevertAssert();
+#endif
+ }
+ classes = new Dictionary();
+ rwLock = new ReaderWriterLock();
+ }
+
+ public Type GetDynamicClass(IEnumerable properties)
+ {
+ rwLock.AcquireReaderLock(Timeout.Infinite);
+ try
+ {
+ Signature signature = new Signature(properties);
+ Type type;
+ if (!classes.TryGetValue(signature, out type))
+ {
+ type = CreateDynamicClass(signature.properties);
+ //fixed by https://gitee.com/DUWENINK
+ if (!classes.ContainsKey(signature))
+ {
+ classes.Add(signature, type);
+ }
+ }
+ return type;
+ }
+ finally
+ {
+ rwLock.ReleaseReaderLock();
+ }
+ }
+
+ Type CreateDynamicClass(DynamicProperty[] properties)
+ {
+ LockCookie cookie = rwLock.UpgradeToWriterLock(Timeout.Infinite);
+ try
+ {
+ string typeName = "DynamicClass" + (classCount + 1);
+#if ENABLE_LINQ_PARTIAL_TRUST
+ new ReflectionPermission(PermissionState.Unrestricted).Assert();
+#endif
+ try
+ {
+ TypeBuilder tb = this.module.DefineType(typeName, TypeAttributes.Class |
+ TypeAttributes.Public, typeof(DynamicClass));
+ FieldInfo[] fields = GenerateProperties(tb, properties);
+ GenerateEquals(tb, fields);
+ GenerateGetHashCode(tb, fields);
+ Type result = tb.CreateType();
+ classCount++;
+ return result;
+ }
+ finally
+ {
+#if ENABLE_LINQ_PARTIAL_TRUST
+ PermissionSet.RevertAssert();
+#endif
+ }
+ }
+ finally
+ {
+ rwLock.DowngradeFromWriterLock(ref cookie);
+ }
+ }
+
+ FieldInfo[] GenerateProperties(TypeBuilder tb, DynamicProperty[] properties)
+ {
+ FieldInfo[] fields = new FieldBuilder[properties.Length];
+ for (int i = 0; i < properties.Length; i++)
+ {
+ DynamicProperty dp = properties[i];
+ FieldBuilder fb = tb.DefineField("_" + dp.Name, dp.Type, FieldAttributes.Private);
+ PropertyBuilder pb = tb.DefineProperty(dp.Name, PropertyAttributes.HasDefault, dp.Type, null);
+ MethodBuilder mbGet = tb.DefineMethod("get_" + dp.Name,
+ MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig,
+ dp.Type, Type.EmptyTypes);
+ ILGenerator genGet = mbGet.GetILGenerator();
+ genGet.Emit(OpCodes.Ldarg_0);
+ genGet.Emit(OpCodes.Ldfld, fb);
+ genGet.Emit(OpCodes.Ret);
+ MethodBuilder mbSet = tb.DefineMethod("set_" + dp.Name,
+ MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig,
+ null, new Type[] { dp.Type });
+ ILGenerator genSet = mbSet.GetILGenerator();
+ genSet.Emit(OpCodes.Ldarg_0);
+ genSet.Emit(OpCodes.Ldarg_1);
+ genSet.Emit(OpCodes.Stfld, fb);
+ genSet.Emit(OpCodes.Ret);
+ pb.SetGetMethod(mbGet);
+ pb.SetSetMethod(mbSet);
+ fields[i] = fb;
+ }
+ return fields;
+ }
+
+ void GenerateEquals(TypeBuilder tb, FieldInfo[] fields)
+ {
+ MethodBuilder mb = tb.DefineMethod("Equals",
+ MethodAttributes.Public | MethodAttributes.ReuseSlot |
+ MethodAttributes.Virtual | MethodAttributes.HideBySig,
+ typeof(bool), new Type[] { typeof(object) });
+ ILGenerator gen = mb.GetILGenerator();
+ LocalBuilder other = gen.DeclareLocal(tb);
+ Label next = gen.DefineLabel();
+ gen.Emit(OpCodes.Ldarg_1);
+ gen.Emit(OpCodes.Isinst, tb);
+ gen.Emit(OpCodes.Stloc, other);
+ gen.Emit(OpCodes.Ldloc, other);
+ gen.Emit(OpCodes.Brtrue_S, next);
+ gen.Emit(OpCodes.Ldc_I4_0);
+ gen.Emit(OpCodes.Ret);
+ gen.MarkLabel(next);
+ foreach (FieldInfo field in fields)
+ {
+ Type ft = field.FieldType;
+ Type ct = typeof(EqualityComparer<>).MakeGenericType(ft);
+ next = gen.DefineLabel();
+ gen.EmitCall(OpCodes.Call, ct.GetMethod("get_Default"), null);
+ gen.Emit(OpCodes.Ldarg_0);
+ gen.Emit(OpCodes.Ldfld, field);
+ gen.Emit(OpCodes.Ldloc, other);
+ gen.Emit(OpCodes.Ldfld, field);
+ gen.EmitCall(OpCodes.Callvirt, ct.GetMethod("Equals", new Type[] { ft, ft }), null);
+ gen.Emit(OpCodes.Brtrue_S, next);
+ gen.Emit(OpCodes.Ldc_I4_0);
+ gen.Emit(OpCodes.Ret);
+ gen.MarkLabel(next);
+ }
+ gen.Emit(OpCodes.Ldc_I4_1);
+ gen.Emit(OpCodes.Ret);
+ }
+
+ void GenerateGetHashCode(TypeBuilder tb, FieldInfo[] fields)
+ {
+ MethodBuilder mb = tb.DefineMethod("GetHashCode",
+ MethodAttributes.Public | MethodAttributes.ReuseSlot |
+ MethodAttributes.Virtual | MethodAttributes.HideBySig,
+ typeof(int), Type.EmptyTypes);
+ ILGenerator gen = mb.GetILGenerator();
+ gen.Emit(OpCodes.Ldc_I4_0);
+ foreach (FieldInfo field in fields)
+ {
+ Type ft = field.FieldType;
+ Type ct = typeof(EqualityComparer<>).MakeGenericType(ft);
+ gen.EmitCall(OpCodes.Call, ct.GetMethod("get_Default"), null);
+ gen.Emit(OpCodes.Ldarg_0);
+ gen.Emit(OpCodes.Ldfld, field);
+ gen.EmitCall(OpCodes.Callvirt, ct.GetMethod("GetHashCode", new Type[] { ft }), null);
+ gen.Emit(OpCodes.Xor);
+ }
+ gen.Emit(OpCodes.Ret);
+ }
+ }
+
+ public sealed class ParseException : Exception
+ {
+ int position;
+
+ public ParseException(string message, int position)
+ : base(message)
+ {
+ this.position = position;
+ }
+
+ public int Position
+ {
+ get { return position; }
+ }
+
+ public override string ToString()
+ {
+ return string.Format(Res.ParseExceptionFormat, Message, position);
+ }
+ }
+
+ internal class ExpressionParser
+ {
+ struct Token
+ {
+ public TokenId id;
+ public string text;
+ public int pos;
+ }
+
+ enum TokenId
+ {
+ Unknown,
+ End,
+ Identifier,
+ StringLiteral,
+ IntegerLiteral,
+ RealLiteral,
+ Exclamation,
+ Percent,
+ Amphersand,
+ OpenParen,
+ CloseParen,
+ Asterisk,
+ Plus,
+ Comma,
+ Minus,
+ Dot,
+ Slash,
+ Colon,
+ LessThan,
+ Equal,
+ GreaterThan,
+ Question,
+ OpenBracket,
+ CloseBracket,
+ Bar,
+ ExclamationEqual,
+ DoubleAmphersand,
+ LessThanEqual,
+ LessGreater,
+ DoubleEqual,
+ GreaterThanEqual,
+ DoubleBar
+ }
+
+ interface ILogicalSignatures
+ {
+ void F(bool x, bool y);
+ void F(bool? x, bool? y);
+ }
+
+ interface IArithmeticSignatures
+ {
+ void F(int x, int y);
+ void F(uint x, uint y);
+ void F(long x, long y);
+ void F(ulong x, ulong y);
+ void F(float x, float y);
+ void F(double x, double y);
+ void F(decimal x, decimal y);
+ void F(int? x, int? y);
+ void F(uint? x, uint? y);
+ void F(long? x, long? y);
+ void F(ulong? x, ulong? y);
+ void F(float? x, float? y);
+ void F(double? x, double? y);
+ void F(decimal? x, decimal? y);
+ }
+
+ interface IRelationalSignatures : IArithmeticSignatures
+ {
+ void F(string x, string y);
+ void F(char x, char y);
+ void F(DateTime x, DateTime y);
+ void F(TimeSpan x, TimeSpan y);
+ void F(char? x, char? y);
+ void F(DateTime? x, DateTime? y);
+ void F(TimeSpan? x, TimeSpan? y);
+ }
+
+ interface IEqualitySignatures : IRelationalSignatures
+ {
+ void F(bool x, bool y);
+ void F(bool? x, bool? y);
+ }
+
+ interface IAddSignatures : IArithmeticSignatures
+ {
+ void F(DateTime x, TimeSpan y);
+ void F(TimeSpan x, TimeSpan y);
+ void F(DateTime? x, TimeSpan? y);
+ void F(TimeSpan? x, TimeSpan? y);
+ }
+
+ interface ISubtractSignatures : IAddSignatures
+ {
+ void F(DateTime x, DateTime y);
+ void F(DateTime? x, DateTime? y);
+ }
+
+ interface INegationSignatures
+ {
+ void F(int x);
+ void F(long x);
+ void F(float x);
+ void F(double x);
+ void F(decimal x);
+ void F(int? x);
+ void F(long? x);
+ void F(float? x);
+ void F(double? x);
+ void F(decimal? x);
+ }
+
+ interface INotSignatures
+ {
+ void F(bool x);
+ void F(bool? x);
+ }
+
+ interface IEnumerableSignatures
+ {
+ void Where(bool predicate);
+ void Any();
+ void Any(bool predicate);
+ void All(bool predicate);
+ void Count();
+ void Count(bool predicate);
+ void Min(object selector);
+ void Max(object selector);
+ void Sum(int selector);
+ void Sum(int? selector);
+ void Sum(long selector);
+ void Sum(long? selector);
+ void Sum(float selector);
+ void Sum(float? selector);
+ void Sum(double selector);
+ void Sum(double? selector);
+ void Sum(decimal selector);
+ void Sum(decimal? selector);
+ void Average(int selector);
+ void Average(int? selector);
+ void Average(long selector);
+ void Average(long? selector);
+ void Average(float selector);
+ void Average(float? selector);
+ void Average(double selector);
+ void Average(double? selector);
+ void Average(decimal selector);
+ void Average(decimal? selector);
+ }
+
+ static readonly Type[] predefinedTypes = {
+ typeof(Object),
+ typeof(Boolean),
+ typeof(Char),
+ typeof(String),
+ typeof(SByte),
+ typeof(Byte),
+ typeof(Int16),
+ typeof(UInt16),
+ typeof(Int32),
+ typeof(UInt32),
+ typeof(Int64),
+ typeof(UInt64),
+ typeof(Single),
+ typeof(Double),
+ typeof(Decimal),
+ typeof(DateTime),
+ typeof(TimeSpan),
+ typeof(Guid),
+ typeof(Math),
+ typeof(Convert)
+ };
+
+ static readonly Expression trueLiteral = Expression.Constant(true);
+ static readonly Expression falseLiteral = Expression.Constant(false);
+ static readonly Expression nullLiteral = Expression.Constant(null);
+
+ static readonly string keywordIt = "it";
+ static readonly string keywordIif = "iif";
+ static readonly string keywordNew = "new";
+
+ static Dictionary keywords;
+
+ Dictionary symbols;
+ IDictionary externals;
+ Dictionary literals;
+ ParameterExpression it;
+ string text;
+ int textPos;
+ int textLen;
+ char ch;
+ Token token;
+
+ public ExpressionParser(ParameterExpression[] parameters, string expression, object[] values)
+ {
+ if (expression == null) throw new ArgumentNullException("expression");
+ if (keywords == null) keywords = CreateKeywords();
+ symbols = new Dictionary(StringComparer.OrdinalIgnoreCase);
+ literals = new Dictionary();
+ if (parameters != null) ProcessParameters(parameters);
+ if (values != null) ProcessValues(values);
+ text = expression;
+ textLen = text.Length;
+ SetTextPos(0);
+ NextToken();
+ }
+
+ void ProcessParameters(ParameterExpression[] parameters)
+ {
+ foreach (ParameterExpression pe in parameters)
+ if (!string.IsNullOrEmpty(pe.Name))
+ AddSymbol(pe.Name, pe);
+ if (parameters.Length == 1 && string.IsNullOrEmpty(parameters[0].Name))
+ it = parameters[0];
+ }
+
+ void ProcessValues(object[] values)
+ {
+ for (int i = 0; i < values.Length; i++)
+ {
+ object value = values[i];
+ if (i == values.Length - 1 && value is IDictionary)
+ {
+ externals = (IDictionary)value;
+ }
+ else
+ {
+ AddSymbol("@" + i.ToString(System.Globalization.CultureInfo.InvariantCulture), value);
+ }
+ }
+ }
+
+ void AddSymbol(string name, object value)
+ {
+ if (symbols.ContainsKey(name))
+ throw ParseError(Res.DuplicateIdentifier, name);
+ symbols.Add(name, value);
+ }
+
+ public Expression Parse(Type resultType)
+ {
+ int exprPos = token.pos;
+ Expression expr = ParseExpression();
+ if (resultType != null)
+ if ((expr = PromoteExpression(expr, resultType, true)) == null)
+ throw ParseError(exprPos, Res.ExpressionTypeMismatch, GetTypeName(resultType));
+ ValidateToken(TokenId.End, Res.SyntaxError);
+ return expr;
+ }
+
+#pragma warning disable 0219
+ public IEnumerable ParseOrdering()
+ {
+ List orderings = new List();
+ while (true)
+ {
+ Expression expr = ParseExpression();
+ bool ascending = true;
+ if (TokenIdentifierIs("asc") || TokenIdentifierIs("ascending"))
+ {
+ NextToken();
+ }
+ else if (TokenIdentifierIs("desc") || TokenIdentifierIs("descending"))
+ {
+ NextToken();
+ ascending = false;
+ }
+ orderings.Add(new DynamicOrdering { Selector = expr, Ascending = ascending });
+ if (token.id != TokenId.Comma) break;
+ NextToken();
+ }
+ ValidateToken(TokenId.End, Res.SyntaxError);
+ return orderings;
+ }
+#pragma warning restore 0219
+
+ // ?: operator
+ Expression ParseExpression()
+ {
+ int errorPos = token.pos;
+ Expression expr = ParseLogicalOr();
+ if (token.id == TokenId.Question)
+ {
+ NextToken();
+ Expression expr1 = ParseExpression();
+ ValidateToken(TokenId.Colon, Res.ColonExpected);
+ NextToken();
+ Expression expr2 = ParseExpression();
+ expr = GenerateConditional(expr, expr1, expr2, errorPos);
+ }
+ return expr;
+ }
+
+ // ||, or operator
+ Expression ParseLogicalOr()
+ {
+ Expression left = ParseLogicalAnd();
+ while (token.id == TokenId.DoubleBar || TokenIdentifierIs("or"))
+ {
+ Token op = token;
+ NextToken();
+ Expression right = ParseLogicalAnd();
+ CheckAndPromoteOperands(typeof(ILogicalSignatures), op.text, ref left, ref right, op.pos);
+ left = Expression.OrElse(left, right);
+ }
+ return left;
+ }
+
+ // &&, and operator
+ Expression ParseLogicalAnd()
+ {
+ Expression left = ParseComparison();
+ while (token.id == TokenId.DoubleAmphersand || TokenIdentifierIs("and"))
+ {
+ Token op = token;
+ NextToken();
+ Expression right = ParseComparison();
+ CheckAndPromoteOperands(typeof(ILogicalSignatures), op.text, ref left, ref right, op.pos);
+ left = Expression.AndAlso(left, right);
+ }
+ return left;
+ }
+
+ // =, ==, !=, <>, >, >=, <, <= operators
+ Expression ParseComparison()
+ {
+ Expression left = ParseAdditive();
+ while (token.id == TokenId.Equal || token.id == TokenId.DoubleEqual ||
+ token.id == TokenId.ExclamationEqual || token.id == TokenId.LessGreater ||
+ token.id == TokenId.GreaterThan || token.id == TokenId.GreaterThanEqual ||
+ token.id == TokenId.LessThan || token.id == TokenId.LessThanEqual)
+ {
+ Token op = token;
+ NextToken();
+ Expression right = ParseAdditive();
+ bool isEquality = op.id == TokenId.Equal || op.id == TokenId.DoubleEqual ||
+ op.id == TokenId.ExclamationEqual || op.id == TokenId.LessGreater;
+ if (isEquality && !left.Type.IsValueType && !right.Type.IsValueType)
+ {
+ if (left.Type != right.Type)
+ {
+ if (left.Type.IsAssignableFrom(right.Type))
+ {
+ right = Expression.Convert(right, left.Type);
+ }
+ else if (right.Type.IsAssignableFrom(left.Type))
+ {
+ left = Expression.Convert(left, right.Type);
+ }
+ else
+ {
+ throw IncompatibleOperandsError(op.text, left, right, op.pos);
+ }
+ }
+ }
+ else if (IsEnumType(left.Type) || IsEnumType(right.Type))
+ {
+ if (left.Type != right.Type)
+ {
+ Expression e;
+ if ((e = PromoteExpression(right, left.Type, true)) != null)
+ {
+ right = e;
+ }
+ else if ((e = PromoteExpression(left, right.Type, true)) != null)
+ {
+ left = e;
+ }
+ else
+ {
+ throw IncompatibleOperandsError(op.text, left, right, op.pos);
+ }
+ }
+ }
+ else
+ {
+ CheckAndPromoteOperands(isEquality ? typeof(IEqualitySignatures) : typeof(IRelationalSignatures),
+ op.text, ref left, ref right, op.pos);
+ }
+ switch (op.id)
+ {
+ case TokenId.Equal:
+ case TokenId.DoubleEqual:
+ left = GenerateEqual(left, right);
+ break;
+ case TokenId.ExclamationEqual:
+ case TokenId.LessGreater:
+ left = GenerateNotEqual(left, right);
+ break;
+ case TokenId.GreaterThan:
+ left = GenerateGreaterThan(left, right);
+ break;
+ case TokenId.GreaterThanEqual:
+ left = GenerateGreaterThanEqual(left, right);
+ break;
+ case TokenId.LessThan:
+ left = GenerateLessThan(left, right);
+ break;
+ case TokenId.LessThanEqual:
+ left = GenerateLessThanEqual(left, right);
+ break;
+ }
+ }
+ return left;
+ }
+
+ // +, -, & operators
+ Expression ParseAdditive()
+ {
+ Expression left = ParseMultiplicative();
+ while (token.id == TokenId.Plus || token.id == TokenId.Minus ||
+ token.id == TokenId.Amphersand)
+ {
+ Token op = token;
+ NextToken();
+ Expression right = ParseMultiplicative();
+ switch (op.id)
+ {
+ case TokenId.Plus:
+ if (left.Type == typeof(string) || right.Type == typeof(string))
+ goto case TokenId.Amphersand;
+ CheckAndPromoteOperands(typeof(IAddSignatures), op.text, ref left, ref right, op.pos);
+ left = GenerateAdd(left, right);
+ break;
+ case TokenId.Minus:
+ CheckAndPromoteOperands(typeof(ISubtractSignatures), op.text, ref left, ref right, op.pos);
+ left = GenerateSubtract(left, right);
+ break;
+ case TokenId.Amphersand:
+ left = GenerateStringConcat(left, right);
+ break;
+ }
+ }
+ return left;
+ }
+
+ // *, /, %, mod operators
+ Expression ParseMultiplicative()
+ {
+ Expression left = ParseUnary();
+ while (token.id == TokenId.Asterisk || token.id == TokenId.Slash ||
+ token.id == TokenId.Percent || TokenIdentifierIs("mod"))
+ {
+ Token op = token;
+ NextToken();
+ Expression right = ParseUnary();
+ CheckAndPromoteOperands(typeof(IArithmeticSignatures), op.text, ref left, ref right, op.pos);
+ switch (op.id)
+ {
+ case TokenId.Asterisk:
+ left = Expression.Multiply(left, right);
+ break;
+ case TokenId.Slash:
+ left = Expression.Divide(left, right);
+ break;
+ case TokenId.Percent:
+ case TokenId.Identifier:
+ left = Expression.Modulo(left, right);
+ break;
+ }
+ }
+ return left;
+ }
+
+ // -, !, not unary operators
+ Expression ParseUnary()
+ {
+ if (token.id == TokenId.Minus || token.id == TokenId.Exclamation ||
+ TokenIdentifierIs("not"))
+ {
+ Token op = token;
+ NextToken();
+ if (op.id == TokenId.Minus && (token.id == TokenId.IntegerLiteral ||
+ token.id == TokenId.RealLiteral))
+ {
+ token.text = "-" + token.text;
+ token.pos = op.pos;
+ return ParsePrimary();
+ }
+ Expression expr = ParseUnary();
+ if (op.id == TokenId.Minus)
+ {
+ CheckAndPromoteOperand(typeof(INegationSignatures), op.text, ref expr, op.pos);
+ expr = Expression.Negate(expr);
+ }
+ else
+ {
+ CheckAndPromoteOperand(typeof(INotSignatures), op.text, ref expr, op.pos);
+ expr = Expression.Not(expr);
+ }
+ return expr;
+ }
+ return ParsePrimary();
+ }
+
+ Expression ParsePrimary()
+ {
+ Expression expr = ParsePrimaryStart();
+ while (true)
+ {
+ if (token.id == TokenId.Dot)
+ {
+ NextToken();
+ expr = ParseMemberAccess(null, expr);
+ }
+ else if (token.id == TokenId.OpenBracket)
+ {
+ expr = ParseElementAccess(expr);
+ }
+ else
+ {
+ break;
+ }
+ }
+ return expr;
+ }
+
+ Expression ParsePrimaryStart()
+ {
+ switch (token.id)
+ {
+ case TokenId.Identifier:
+ return ParseIdentifier();
+ case TokenId.StringLiteral:
+ return ParseStringLiteral();
+ case TokenId.IntegerLiteral:
+ return ParseIntegerLiteral();
+ case TokenId.RealLiteral:
+ return ParseRealLiteral();
+ case TokenId.OpenParen:
+ return ParseParenExpression();
+ default:
+ throw ParseError(Res.ExpressionExpected);
+ }
+ }
+
+ Expression ParseStringLiteral()
+ {
+ ValidateToken(TokenId.StringLiteral);
+ char quote = token.text[0];
+ string s = token.text.Substring(1, token.text.Length - 2);
+ int start = 0;
+ while (true)
+ {
+ int i = s.IndexOf(quote, start);
+ if (i < 0) break;
+ s = s.Remove(i, 1);
+ start = i + 1;
+ }
+ //if (quote == '\'') {
+ // if (s.Length != 1)
+ // throw ParseError(Res.InvalidCharacterLiteral);
+ // NextToken();
+ // return CreateLiteral(s[0], s);
+ //}
+ NextToken();
+ return CreateLiteral(s, s);
+ }
+
+ Expression ParseIntegerLiteral()
+ {
+ ValidateToken(TokenId.IntegerLiteral);
+ string text = token.text;
+ if (text[0] != '-')
+ {
+ ulong value;
+ if (!UInt64.TryParse(text, out value))
+ throw ParseError(Res.InvalidIntegerLiteral, text);
+ NextToken();
+ if (value <= int.MaxValue) return CreateLiteral((int)value, text);
+ if (value <= uint.MaxValue) return CreateLiteral((uint)value, text);
+ if (value <= long.MaxValue) return CreateLiteral((long)value, text);
+ return CreateLiteral(value, text);
+ }
+ else
+ {
+ long value;
+ if (!Int64.TryParse(text, out value))
+ throw ParseError(Res.InvalidIntegerLiteral, text);
+ NextToken();
+ if (value >= Int32.MinValue && value <= Int32.MaxValue)
+ return CreateLiteral((int)value, text);
+ return CreateLiteral(value, text);
+ }
+ }
+
+ Expression ParseRealLiteral()
+ {
+ ValidateToken(TokenId.RealLiteral);
+ string text = token.text;
+ object value = null;
+ char last = text[text.Length - 1];
+ if (last == 'F' || last == 'f')
+ {
+ float f;
+ if (Single.TryParse(text.Substring(0, text.Length - 1), out f)) value = f;
+ }
+ else
+ {
+ double d;
+ if (Double.TryParse(text, out d)) value = d;
+ }
+ if (value == null) throw ParseError(Res.InvalidRealLiteral, text);
+ NextToken();
+ return CreateLiteral(value, text);
+ }
+
+ Expression CreateLiteral(object value, string text)
+ {
+ ConstantExpression expr = Expression.Constant(value);
+ literals.Add(expr, text);
+ return expr;
+ }
+
+ Expression ParseParenExpression()
+ {
+ ValidateToken(TokenId.OpenParen, Res.OpenParenExpected);
+ NextToken();
+ Expression e = ParseExpression();
+ ValidateToken(TokenId.CloseParen, Res.CloseParenOrOperatorExpected);
+ NextToken();
+ return e;
+ }
+
+ Expression ParseIdentifier()
+ {
+ ValidateToken(TokenId.Identifier);
+ object value;
+ if (keywords.TryGetValue(token.text, out value))
+ {
+ if (value is Type) return ParseTypeAccess((Type)value);
+ if (value == (object)keywordIt) return ParseIt();
+ if (value == (object)keywordIif) return ParseIif();
+ if (value == (object)keywordNew) return ParseNew();
+ NextToken();
+ return (Expression)value;
+ }
+ if (symbols.TryGetValue(token.text, out value) ||
+ externals != null && externals.TryGetValue(token.text, out value))
+ {
+ Expression expr = value as Expression;
+ if (expr == null)
+ {
+ expr = Expression.Constant(value);
+ }
+ else
+ {
+ LambdaExpression lambda = expr as LambdaExpression;
+ if (lambda != null) return ParseLambdaInvocation(lambda);
+ }
+ NextToken();
+ return expr;
+ }
+ if (it != null) return ParseMemberAccess(null, it);
+ throw ParseError(Res.UnknownIdentifier, token.text);
+ }
+
+ Expression ParseIt()
+ {
+ if (it == null)
+ throw ParseError(Res.NoItInScope);
+ NextToken();
+ return it;
+ }
+
+ Expression ParseIif()
+ {
+ int errorPos = token.pos;
+ NextToken();
+ Expression[] args = ParseArgumentList();
+ if (args.Length != 3)
+ throw ParseError(errorPos, Res.IifRequiresThreeArgs);
+ return GenerateConditional(args[0], args[1], args[2], errorPos);
+ }
+
+ Expression GenerateConditional(Expression test, Expression expr1, Expression expr2, int errorPos)
+ {
+ if (test.Type != typeof(bool))
+ throw ParseError(errorPos, Res.FirstExprMustBeBool);
+ if (expr1.Type != expr2.Type)
+ {
+ Expression expr1as2 = expr2 != nullLiteral ? PromoteExpression(expr1, expr2.Type, true) : null;
+ Expression expr2as1 = expr1 != nullLiteral ? PromoteExpression(expr2, expr1.Type, true) : null;
+ if (expr1as2 != null && expr2as1 == null)
+ {
+ expr1 = expr1as2;
+ }
+ else if (expr2as1 != null && expr1as2 == null)
+ {
+ expr2 = expr2as1;
+ }
+ else
+ {
+ string type1 = expr1 != nullLiteral ? expr1.Type.Name : "null";
+ string type2 = expr2 != nullLiteral ? expr2.Type.Name : "null";
+ if (expr1as2 != null && expr2as1 != null)
+ throw ParseError(errorPos, Res.BothTypesConvertToOther, type1, type2);
+ throw ParseError(errorPos, Res.NeitherTypeConvertsToOther, type1, type2);
+ }
+ }
+ return Expression.Condition(test, expr1, expr2);
+ }
+
+ Expression ParseNew()
+ {
+ NextToken();
+ ValidateToken(TokenId.OpenParen, Res.OpenParenExpected);
+ NextToken();
+ List properties = new List();
+ List expressions = new List();
+ while (true)
+ {
+ int exprPos = token.pos;
+ Expression expr = ParseExpression();
+ string propName;
+ if (TokenIdentifierIs("as"))
+ {
+ NextToken();
+ propName = GetIdentifier();
+ NextToken();
+ }
+ else
+ {
+ MemberExpression me = expr as MemberExpression;
+ if (me == null) throw ParseError(exprPos, Res.MissingAsClause);
+ propName = me.Member.Name;
+ }
+ expressions.Add(expr);
+ properties.Add(new DynamicProperty(propName, expr.Type));
+ if (token.id != TokenId.Comma) break;
+ NextToken();
+ }
+ ValidateToken(TokenId.CloseParen, Res.CloseParenOrCommaExpected);
+ NextToken();
+ Type type = DynamicExpression.CreateClass(properties);
+ MemberBinding[] bindings = new MemberBinding[properties.Count];
+ for (int i = 0; i < bindings.Length; i++)
+ bindings[i] = Expression.Bind(type.GetProperty(properties[i].Name), expressions[i]);
+ return Expression.MemberInit(Expression.New(type), bindings);
+ }
+
+ Expression ParseLambdaInvocation(LambdaExpression lambda)
+ {
+ int errorPos = token.pos;
+ NextToken();
+ Expression[] args = ParseArgumentList();
+ MethodBase method;
+ if (FindMethod(lambda.Type, "Invoke", false, args, out method) != 1)
+ throw ParseError(errorPos, Res.ArgsIncompatibleWithLambda);
+ return Expression.Invoke(lambda, args);
+ }
+
+ Expression ParseTypeAccess(Type type)
+ {
+ int errorPos = token.pos;
+ NextToken();
+ if (token.id == TokenId.Question)
+ {
+ if (!type.IsValueType || IsNullableType(type))
+ throw ParseError(errorPos, Res.TypeHasNoNullableForm, GetTypeName(type));
+ type = typeof(Nullable<>).MakeGenericType(type);
+ NextToken();
+ }
+ if (token.id == TokenId.OpenParen)
+ {
+ Expression[] args = ParseArgumentList();
+ MethodBase method;
+ switch (FindBestMethod(type.GetConstructors(), args, out method))
+ {
+ case 0:
+ if (args.Length == 1)
+ return GenerateConversion(args[0], type, errorPos);
+ throw ParseError(errorPos, Res.NoMatchingConstructor, GetTypeName(type));
+ case 1:
+ return Expression.New((ConstructorInfo)method, args);
+ default:
+ throw ParseError(errorPos, Res.AmbiguousConstructorInvocation, GetTypeName(type));
+ }
+ }
+ ValidateToken(TokenId.Dot, Res.DotOrOpenParenExpected);
+ NextToken();
+ return ParseMemberAccess(type, null);
+ }
+
+ Expression GenerateConversion(Expression expr, Type type, int errorPos)
+ {
+ Type exprType = expr.Type;
+ if (exprType == type) return expr;
+ if (exprType.IsValueType && type.IsValueType)
+ {
+ if ((IsNullableType(exprType) || IsNullableType(type)) &&
+ GetNonNullableType(exprType) == GetNonNullableType(type))
+ return Expression.Convert(expr, type);
+ if ((IsNumericType(exprType) || IsEnumType(exprType)) &&
+ (IsNumericType(type)) || IsEnumType(type))
+ return Expression.ConvertChecked(expr, type);
+ }
+ if (exprType.IsAssignableFrom(type) || type.IsAssignableFrom(exprType) ||
+ exprType.IsInterface || type.IsInterface)
+ return Expression.Convert(expr, type);
+ throw ParseError(errorPos, Res.CannotConvertValue,
+ GetTypeName(exprType), GetTypeName(type));
+ }
+
+ Expression ParseMemberAccess(Type type, Expression instance)
+ {
+ if (instance != null) type = instance.Type;
+ int errorPos = token.pos;
+ string id = GetIdentifier();
+ NextToken();
+ if (token.id == TokenId.OpenParen)
+ {
+ if (instance != null && type != typeof(string))
+ {
+ Type enumerableType = FindGenericType(typeof(IEnumerable<>), type);
+ if (enumerableType != null)
+ {
+ Type elementType = enumerableType.GetGenericArguments()[0];
+ return ParseAggregate(instance, elementType, id, errorPos);
+ }
+ }
+ Expression[] args = ParseArgumentList();
+ MethodBase mb;
+ switch (FindMethod(type, id, instance == null, args, out mb))
+ {
+ case 0:
+ throw ParseError(errorPos, Res.NoApplicableMethod,
+ id, GetTypeName(type));
+ case 1:
+ MethodInfo method = (MethodInfo)mb;
+ if (!IsPredefinedType(method.DeclaringType))
+ throw ParseError(errorPos, Res.MethodsAreInaccessible, GetTypeName(method.DeclaringType));
+ if (method.ReturnType == typeof(void))
+ throw ParseError(errorPos, Res.MethodIsVoid,
+ id, GetTypeName(method.DeclaringType));
+ return Expression.Call(instance, method, args);
+ default:
+ throw ParseError(errorPos, Res.AmbiguousMethodInvocation,
+ id, GetTypeName(type));
+ }
+ }
+ else
+ {
+ MemberInfo member = FindPropertyOrField(type, id, instance == null);
+ if (member == null)
+ throw ParseError(errorPos, Res.UnknownPropertyOrField,
+ id, GetTypeName(type));
+ return member is PropertyInfo ?
+ Expression.Property(instance, (PropertyInfo)member) :
+ Expression.Field(instance, (FieldInfo)member);
+ }
+ }
+
+ static Type FindGenericType(Type generic, Type type)
+ {
+ while (type != null && type != typeof(object))
+ {
+ if (type.IsGenericType && type.GetGenericTypeDefinition() == generic) return type;
+ if (generic.IsInterface)
+ {
+ foreach (Type intfType in type.GetInterfaces())
+ {
+ Type found = FindGenericType(generic, intfType);
+ if (found != null) return found;
+ }
+ }
+ type = type.BaseType;
+ }
+ return null;
+ }
+
+ Expression ParseAggregate(Expression instance, Type elementType, string methodName, int errorPos)
+ {
+ ParameterExpression outerIt = it;
+ ParameterExpression innerIt = Expression.Parameter(elementType, "");
+ it = innerIt;
+ Expression[] args = ParseArgumentList();
+ it = outerIt;
+ MethodBase signature;
+ if (FindMethod(typeof(IEnumerableSignatures), methodName, false, args, out signature) != 1)
+ throw ParseError(errorPos, Res.NoApplicableAggregate, methodName);
+ Type[] typeArgs;
+ if (signature.Name == "Min" || signature.Name == "Max")
+ {
+ typeArgs = new Type[] { elementType, args[0].Type };
+ }
+ else
+ {
+ typeArgs = new Type[] { elementType };
+ }
+ if (args.Length == 0)
+ {
+ args = new Expression[] { instance };
+ }
+ else
+ {
+ args = new Expression[] { instance, Expression.Lambda(args[0], innerIt) };
+ }
+ return Expression.Call(typeof(Enumerable), signature.Name, typeArgs, args);
+ }
+
+ Expression[] ParseArgumentList()
+ {
+ ValidateToken(TokenId.OpenParen, Res.OpenParenExpected);
+ NextToken();
+ Expression[] args = token.id != TokenId.CloseParen ? ParseArguments() : new Expression[0];
+ ValidateToken(TokenId.CloseParen, Res.CloseParenOrCommaExpected);
+ NextToken();
+ return args;
+ }
+
+ Expression[] ParseArguments()
+ {
+ List argList = new List();
+ while (true)
+ {
+ argList.Add(ParseExpression());
+ if (token.id != TokenId.Comma) break;
+ NextToken();
+ }
+ return argList.ToArray();
+ }
+
+ Expression ParseElementAccess(Expression expr)
+ {
+ int errorPos = token.pos;
+ ValidateToken(TokenId.OpenBracket, Res.OpenParenExpected);
+ NextToken();
+ Expression[] args = ParseArguments();
+ ValidateToken(TokenId.CloseBracket, Res.CloseBracketOrCommaExpected);
+ NextToken();
+ if (expr.Type.IsArray)
+ {
+ if (expr.Type.GetArrayRank() != 1 || args.Length != 1)
+ throw ParseError(errorPos, Res.CannotIndexMultiDimArray);
+ Expression index = PromoteExpression(args[0], typeof(int), true);
+ if (index == null)
+ throw ParseError(errorPos, Res.InvalidIndex);
+ return Expression.ArrayIndex(expr, index);
+ }
+ else
+ {
+ MethodBase mb;
+ switch (FindIndexer(expr.Type, args, out mb))
+ {
+ case 0:
+ throw ParseError(errorPos, Res.NoApplicableIndexer,
+ GetTypeName(expr.Type));
+ case 1:
+ return Expression.Call(expr, (MethodInfo)mb, args);
+ default:
+ throw ParseError(errorPos, Res.AmbiguousIndexerInvocation,
+ GetTypeName(expr.Type));
+ }
+ }
+ }
+
+ static bool IsPredefinedType(Type type)
+ {
+ foreach (Type t in predefinedTypes) if (t == type) return true;
+ return false;
+ }
+
+ static bool IsNullableType(Type type)
+ {
+ return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>);
+ }
+
+ static Type GetNonNullableType(Type type)
+ {
+ return IsNullableType(type) ? type.GetGenericArguments()[0] : type;
+ }
+
+ static string GetTypeName(Type type)
+ {
+ Type baseType = GetNonNullableType(type);
+ string s = baseType.Name;
+ if (type != baseType) s += '?';
+ return s;
+ }
+
+ static bool IsNumericType(Type type)
+ {
+ return GetNumericTypeKind(type) != 0;
+ }
+
+ static bool IsSignedIntegralType(Type type)
+ {
+ return GetNumericTypeKind(type) == 2;
+ }
+
+ static bool IsUnsignedIntegralType(Type type)
+ {
+ return GetNumericTypeKind(type) == 3;
+ }
+
+ static int GetNumericTypeKind(Type type)
+ {
+ type = GetNonNullableType(type);
+ if (type.IsEnum) return 0;
+ switch (Type.GetTypeCode(type))
+ {
+ case TypeCode.Char:
+ case TypeCode.Single:
+ case TypeCode.Double:
+ case TypeCode.Decimal:
+ return 1;
+ case TypeCode.SByte:
+ case TypeCode.Int16:
+ case TypeCode.Int32:
+ case TypeCode.Int64:
+ return 2;
+ case TypeCode.Byte:
+ case TypeCode.UInt16:
+ case TypeCode.UInt32:
+ case TypeCode.UInt64:
+ return 3;
+ default:
+ return 0;
+ }
+ }
+
+ static bool IsEnumType(Type type)
+ {
+ return GetNonNullableType(type).IsEnum;
+ }
+
+ void CheckAndPromoteOperand(Type signatures, string opName, ref Expression expr, int errorPos)
+ {
+ Expression[] args = new Expression[] { expr };
+ MethodBase method;
+ if (FindMethod(signatures, "F", false, args, out method) != 1)
+ throw ParseError(errorPos, Res.IncompatibleOperand,
+ opName, GetTypeName(args[0].Type));
+ expr = args[0];
+ }
+
+ void CheckAndPromoteOperands(Type signatures, string opName, ref Expression left, ref Expression right, int errorPos)
+ {
+ Expression[] args = new Expression[] { left, right };
+ MethodBase method;
+ if (FindMethod(signatures, "F", false, args, out method) != 1)
+ throw IncompatibleOperandsError(opName, left, right, errorPos);
+ left = args[0];
+ right = args[1];
+ }
+
+ Exception IncompatibleOperandsError(string opName, Expression left, Expression right, int pos)
+ {
+ return ParseError(pos, Res.IncompatibleOperands,
+ opName, GetTypeName(left.Type), GetTypeName(right.Type));
+ }
+
+ MemberInfo FindPropertyOrField(Type type, string memberName, bool staticAccess)
+ {
+ BindingFlags flags = BindingFlags.Public | BindingFlags.DeclaredOnly |
+ (staticAccess ? BindingFlags.Static : BindingFlags.Instance);
+ foreach (Type t in SelfAndBaseTypes(type))
+ {
+ MemberInfo[] members = t.FindMembers(MemberTypes.Property | MemberTypes.Field,
+ flags, Type.FilterNameIgnoreCase, memberName);
+ if (members.Length != 0) return members[0];
+ }
+ return null;
+ }
+
+ int FindMethod(Type type, string methodName, bool staticAccess, Expression[] args, out MethodBase method)
+ {
+ BindingFlags flags = BindingFlags.Public | BindingFlags.DeclaredOnly |
+ (staticAccess ? BindingFlags.Static : BindingFlags.Instance);
+ foreach (Type t in SelfAndBaseTypes(type))
+ {
+ MemberInfo[] members = t.FindMembers(MemberTypes.Method,
+ flags, Type.FilterNameIgnoreCase, methodName);
+ int count = FindBestMethod(members.Cast(), args, out method);
+ if (count != 0) return count;
+ }
+ method = null;
+ return 0;
+ }
+
+ int FindIndexer(Type type, Expression[] args, out MethodBase method)
+ {
+ foreach (Type t in SelfAndBaseTypes(type))
+ {
+ MemberInfo[] members = t.GetDefaultMembers();
+ if (members.Length != 0)
+ {
+ IEnumerable methods = members.
+ OfType().
+ Select(p => (MethodBase)p.GetGetMethod()).
+ Where(m => m != null);
+ int count = FindBestMethod(methods, args, out method);
+ if (count != 0) return count;
+ }
+ }
+ method = null;
+ return 0;
+ }
+
+ static IEnumerable SelfAndBaseTypes(Type type)
+ {
+ if (type.IsInterface)
+ {
+ List types = new List();
+ AddInterface(types, type);
+ return types;
+ }
+ return SelfAndBaseClasses(type);
+ }
+
+ static IEnumerable SelfAndBaseClasses(Type type)
+ {
+ while (type != null)
+ {
+ yield return type;
+ type = type.BaseType;
+ }
+ }
+
+ static void AddInterface(List types, Type type)
+ {
+ if (!types.Contains(type))
+ {
+ types.Add(type);
+ foreach (Type t in type.GetInterfaces()) AddInterface(types, t);
+ }
+ }
+
+ class MethodData
+ {
+ public MethodBase MethodBase;
+ public ParameterInfo[] Parameters;
+ public Expression[] Args;
+ }
+
+ int FindBestMethod(IEnumerable methods, Expression[] args, out MethodBase method)
+ {
+ MethodData[] applicable = methods.
+ Select(m => new MethodData { MethodBase = m, Parameters = m.GetParameters() }).
+ Where(m => IsApplicable(m, args)).
+ ToArray();
+ if (applicable.Length > 1)
+ {
+ applicable = applicable.
+ Where(m => applicable.All(n => m == n || IsBetterThan(args, m, n))).
+ ToArray();
+ }
+ if (applicable.Length == 1)
+ {
+ MethodData md = applicable[0];
+ for (int i = 0; i < args.Length; i++) args[i] = md.Args[i];
+ method = md.MethodBase;
+ }
+ else
+ {
+ method = null;
+ }
+ return applicable.Length;
+ }
+
+ bool IsApplicable(MethodData method, Expression[] args)
+ {
+ if (method.Parameters.Length != args.Length) return false;
+ Expression[] promotedArgs = new Expression[args.Length];
+ for (int i = 0; i < args.Length; i++)
+ {
+ ParameterInfo pi = method.Parameters[i];
+ if (pi.IsOut) return false;
+ Expression promoted = PromoteExpression(args[i], pi.ParameterType, false);
+ if (promoted == null) return false;
+ promotedArgs[i] = promoted;
+ }
+ method.Args = promotedArgs;
+ return true;
+ }
+
+ Expression PromoteExpression(Expression expr, Type type, bool exact)
+ {
+ if (expr.Type == type) return expr;
+ if (expr is ConstantExpression)
+ {
+ ConstantExpression ce = (ConstantExpression)expr;
+ if (ce == nullLiteral)
+ {
+ if (!type.IsValueType || IsNullableType(type))
+ return Expression.Constant(null, type);
+ }
+ else
+ {
+ string text;
+ if (literals.TryGetValue(ce, out text))
+ {
+ Type target = GetNonNullableType(type);
+ Object value = null;
+ switch (Type.GetTypeCode(ce.Type))
+ {
+ case TypeCode.Int32:
+ case TypeCode.UInt32:
+ case TypeCode.Int64:
+ case TypeCode.UInt64:
+ value = ParseNumber(text, target);
+ break;
+ case TypeCode.Double:
+ if (target == typeof(decimal)) value = ParseNumber(text, target);
+ break;
+ case TypeCode.String:
+ value = ParseEnum(text, target);
+ break;
+ }
+ if (value != null)
+ return Expression.Constant(value, type);
+ }
+ }
+ }
+ if (IsCompatibleWith(expr.Type, type))
+ {
+ if (type.IsValueType || exact) return Expression.Convert(expr, type);
+ return expr;
+ }
+ return null;
+ }
+
+ static object ParseNumber(string text, Type type)
+ {
+ switch (Type.GetTypeCode(GetNonNullableType(type)))
+ {
+ case TypeCode.SByte:
+ sbyte sb;
+ if (sbyte.TryParse(text, out sb)) return sb;
+ break;
+ case TypeCode.Byte:
+ byte b;
+ if (byte.TryParse(text, out b)) return b;
+ break;
+ case TypeCode.Int16:
+ short s;
+ if (short.TryParse(text, out s)) return s;
+ break;
+ case TypeCode.UInt16:
+ ushort us;
+ if (ushort.TryParse(text, out us)) return us;
+ break;
+ case TypeCode.Int32:
+ int i;
+ if (int.TryParse(text, out i)) return i;
+ break;
+ case TypeCode.UInt32:
+ uint ui;
+ if (uint.TryParse(text, out ui)) return ui;
+ break;
+ case TypeCode.Int64:
+ long l;
+ if (long.TryParse(text, out l)) return l;
+ break;
+ case TypeCode.UInt64:
+ ulong ul;
+ if (ulong.TryParse(text, out ul)) return ul;
+ break;
+ case TypeCode.Single:
+ float f;
+ if (float.TryParse(text, out f)) return f;
+ break;
+ case TypeCode.Double:
+ double d;
+ if (double.TryParse(text, out d)) return d;
+ break;
+ case TypeCode.Decimal:
+ decimal e;
+ if (decimal.TryParse(text, out e)) return e;
+ break;
+ }
+ return null;
+ }
+
+ static object ParseEnum(string name, Type type)
+ {
+ if (type.IsEnum)
+ {
+ MemberInfo[] memberInfos = type.FindMembers(MemberTypes.Field,
+ BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Static,
+ Type.FilterNameIgnoreCase, name);
+ if (memberInfos.Length != 0) return ((FieldInfo)memberInfos[0]).GetValue(null);
+ }
+ return null;
+ }
+
+ static bool IsCompatibleWith(Type source, Type target)
+ {
+ if (source == target) return true;
+ if (!target.IsValueType) return target.IsAssignableFrom(source);
+ Type st = GetNonNullableType(source);
+ Type tt = GetNonNullableType(target);
+ if (st != source && tt == target) return false;
+ TypeCode sc = st.IsEnum ? TypeCode.Object : Type.GetTypeCode(st);
+ TypeCode tc = tt.IsEnum ? TypeCode.Object : Type.GetTypeCode(tt);
+ switch (sc)
+ {
+ case TypeCode.SByte:
+ switch (tc)
+ {
+ case TypeCode.SByte:
+ case TypeCode.Int16:
+ case TypeCode.Int32:
+ case TypeCode.Int64:
+ case TypeCode.Single:
+ case TypeCode.Double:
+ case TypeCode.Decimal:
+ return true;
+ }
+ break;
+ case TypeCode.Byte:
+ switch (tc)
+ {
+ case TypeCode.Byte:
+ case TypeCode.Int16:
+ case TypeCode.UInt16:
+ case TypeCode.Int32:
+ case TypeCode.UInt32:
+ case TypeCode.Int64:
+ case TypeCode.UInt64:
+ case TypeCode.Single:
+ case TypeCode.Double:
+ case TypeCode.Decimal:
+ return true;
+ }
+ break;
+ case TypeCode.Int16:
+ switch (tc)
+ {
+ case TypeCode.Int16:
+ case TypeCode.Int32:
+ case TypeCode.Int64:
+ case TypeCode.Single:
+ case TypeCode.Double:
+ case TypeCode.Decimal:
+ return true;
+ }
+ break;
+ case TypeCode.UInt16:
+ switch (tc)
+ {
+ case TypeCode.UInt16:
+ case TypeCode.Int32:
+ case TypeCode.UInt32:
+ case TypeCode.Int64:
+ case TypeCode.UInt64:
+ case TypeCode.Single:
+ case TypeCode.Double:
+ case TypeCode.Decimal:
+ return true;
+ }
+ break;
+ case TypeCode.Int32:
+ switch (tc)
+ {
+ case TypeCode.Int32:
+ case TypeCode.Int64:
+ case TypeCode.Single:
+ case TypeCode.Double:
+ case TypeCode.Decimal:
+ return true;
+ }
+ break;
+ case TypeCode.UInt32:
+ switch (tc)
+ {
+ case TypeCode.UInt32:
+ case TypeCode.Int64:
+ case TypeCode.UInt64:
+ case TypeCode.Single:
+ case TypeCode.Double:
+ case TypeCode.Decimal:
+ return true;
+ }
+ break;
+ case TypeCode.Int64:
+ switch (tc)
+ {
+ case TypeCode.Int64:
+ case TypeCode.Single:
+ case TypeCode.Double:
+ case TypeCode.Decimal:
+ return true;
+ }
+ break;
+ case TypeCode.UInt64:
+ switch (tc)
+ {
+ case TypeCode.UInt64:
+ case TypeCode.Single:
+ case TypeCode.Double:
+ case TypeCode.Decimal:
+ return true;
+ }
+ break;
+ case TypeCode.Single:
+ switch (tc)
+ {
+ case TypeCode.Single:
+ case TypeCode.Double:
+ return true;
+ }
+ break;
+ default:
+ if (st == tt) return true;
+ break;
+ }
+ return false;
+ }
+
+ static bool IsBetterThan(Expression[] args, MethodData m1, MethodData m2)
+ {
+ bool better = false;
+ for (int i = 0; i < args.Length; i++)
+ {
+ int c = CompareConversions(args[i].Type,
+ m1.Parameters[i].ParameterType,
+ m2.Parameters[i].ParameterType);
+ if (c < 0) return false;
+ if (c > 0) better = true;
+ }
+ return better;
+ }
+
+ // Return 1 if s -> t1 is a better conversion than s -> t2
+ // Return -1 if s -> t2 is a better conversion than s -> t1
+ // Return 0 if neither conversion is better
+ static int CompareConversions(Type s, Type t1, Type t2)
+ {
+ if (t1 == t2) return 0;
+ if (s == t1) return 1;
+ if (s == t2) return -1;
+ bool t1t2 = IsCompatibleWith(t1, t2);
+ bool t2t1 = IsCompatibleWith(t2, t1);
+ if (t1t2 && !t2t1) return 1;
+ if (t2t1 && !t1t2) return -1;
+ if (IsSignedIntegralType(t1) && IsUnsignedIntegralType(t2)) return 1;
+ if (IsSignedIntegralType(t2) && IsUnsignedIntegralType(t1)) return -1;
+ return 0;
+ }
+
+ Expression GenerateEqual(Expression left, Expression right)
+ {
+ return Expression.Equal(left, right);
+ }
+
+ Expression GenerateNotEqual(Expression left, Expression right)
+ {
+ return Expression.NotEqual(left, right);
+ }
+
+ Expression GenerateGreaterThan(Expression left, Expression right)
+ {
+ if (left.Type == typeof(string))
+ {
+ return Expression.GreaterThan(
+ GenerateStaticMethodCall("Compare", left, right),
+ Expression.Constant(0)
+ );
+ }
+ return Expression.GreaterThan(left, right);
+ }
+
+ Expression GenerateGreaterThanEqual(Expression left, Expression right)
+ {
+ if (left.Type == typeof(string))
+ {
+ return Expression.GreaterThanOrEqual(
+ GenerateStaticMethodCall("Compare", left, right),
+ Expression.Constant(0)
+ );
+ }
+ return Expression.GreaterThanOrEqual(left, right);
+ }
+
+ Expression GenerateLessThan(Expression left, Expression right)
+ {
+ if (left.Type == typeof(string))
+ {
+ return Expression.LessThan(
+ GenerateStaticMethodCall("Compare", left, right),
+ Expression.Constant(0)
+ );
+ }
+ return Expression.LessThan(left, right);
+ }
+
+ Expression GenerateLessThanEqual(Expression left, Expression right)
+ {
+ if (left.Type == typeof(string))
+ {
+ return Expression.LessThanOrEqual(
+ GenerateStaticMethodCall("Compare", left, right),
+ Expression.Constant(0)
+ );
+ }
+ return Expression.LessThanOrEqual(left, right);
+ }
+
+ Expression GenerateAdd(Expression left, Expression right)
+ {
+ if (left.Type == typeof(string) && right.Type == typeof(string))
+ {
+ return GenerateStaticMethodCall("Concat", left, right);
+ }
+ return Expression.Add(left, right);
+ }
+
+ Expression GenerateSubtract(Expression left, Expression right)
+ {
+ return Expression.Subtract(left, right);
+ }
+
+ Expression GenerateStringConcat(Expression left, Expression right)
+ {
+ return Expression.Call(
+ null,
+ typeof(string).GetMethod("Concat", new[] { typeof(object), typeof(object) }),
+ new[] { left, right });
+ }
+
+ MethodInfo GetStaticMethod(string methodName, Expression left, Expression right)
+ {
+ return left.Type.GetMethod(methodName, new[] { left.Type, right.Type });
+ }
+
+ Expression GenerateStaticMethodCall(string methodName, Expression left, Expression right)
+ {
+ return Expression.Call(null, GetStaticMethod(methodName, left, right), new[] { left, right });
+ }
+
+ void SetTextPos(int pos)
+ {
+ textPos = pos;
+ ch = textPos < textLen ? text[textPos] : '\0';
+ }
+
+ void NextChar()
+ {
+ if (textPos < textLen) textPos++;
+ ch = textPos < textLen ? text[textPos] : '\0';
+ }
+
+ void NextToken()
+ {
+ while (Char.IsWhiteSpace(ch)) NextChar();
+ TokenId t;
+ int tokenPos = textPos;
+ switch (ch)
+ {
+ case '!':
+ NextChar();
+ if (ch == '=')
+ {
+ NextChar();
+ t = TokenId.ExclamationEqual;
+ }
+ else
+ {
+ t = TokenId.Exclamation;
+ }
+ break;
+ case '%':
+ NextChar();
+ t = TokenId.Percent;
+ break;
+ case '&':
+ NextChar();
+ if (ch == '&')
+ {
+ NextChar();
+ t = TokenId.DoubleAmphersand;
+ }
+ else
+ {
+ t = TokenId.Amphersand;
+ }
+ break;
+ case '(':
+ NextChar();
+ t = TokenId.OpenParen;
+ break;
+ case ')':
+ NextChar();
+ t = TokenId.CloseParen;
+ break;
+ case '*':
+ NextChar();
+ t = TokenId.Asterisk;
+ break;
+ case '+':
+ NextChar();
+ t = TokenId.Plus;
+ break;
+ case ',':
+ NextChar();
+ t = TokenId.Comma;
+ break;
+ case '-':
+ NextChar();
+ t = TokenId.Minus;
+ break;
+ case '.':
+ NextChar();
+ t = TokenId.Dot;
+ break;
+ case '/':
+ NextChar();
+ t = TokenId.Slash;
+ break;
+ case ':':
+ NextChar();
+ t = TokenId.Colon;
+ break;
+ case '<':
+ NextChar();
+ if (ch == '=')
+ {
+ NextChar();
+ t = TokenId.LessThanEqual;
+ }
+ else if (ch == '>')
+ {
+ NextChar();
+ t = TokenId.LessGreater;
+ }
+ else
+ {
+ t = TokenId.LessThan;
+ }
+ break;
+ case '=':
+ NextChar();
+ if (ch == '=')
+ {
+ NextChar();
+ t = TokenId.DoubleEqual;
+ }
+ else
+ {
+ t = TokenId.Equal;
+ }
+ break;
+ case '>':
+ NextChar();
+ if (ch == '=')
+ {
+ NextChar();
+ t = TokenId.GreaterThanEqual;
+ }
+ else
+ {
+ t = TokenId.GreaterThan;
+ }
+ break;
+ case '?':
+ NextChar();
+ t = TokenId.Question;
+ break;
+ case '[':
+ NextChar();
+ t = TokenId.OpenBracket;
+ break;
+ case ']':
+ NextChar();
+ t = TokenId.CloseBracket;
+ break;
+ case '|':
+ NextChar();
+ if (ch == '|')
+ {
+ NextChar();
+ t = TokenId.DoubleBar;
+ }
+ else
+ {
+ t = TokenId.Bar;
+ }
+ break;
+ case '"':
+ case '\'':
+ char quote = ch;
+ do
+ {
+ NextChar();
+ while (textPos < textLen && ch != quote) NextChar();
+ if (textPos == textLen)
+ throw ParseError(textPos, Res.UnterminatedStringLiteral);
+ NextChar();
+ } while (ch == quote);
+ t = TokenId.StringLiteral;
+ break;
+ default:
+ if (Char.IsLetter(ch) || ch == '@' || ch == '_')
+ {
+ do
+ {
+ NextChar();
+ } while (Char.IsLetterOrDigit(ch) || ch == '_');
+ t = TokenId.Identifier;
+ break;
+ }
+ if (Char.IsDigit(ch))
+ {
+ t = TokenId.IntegerLiteral;
+ do
+ {
+ NextChar();
+ } while (Char.IsDigit(ch));
+ if (ch == '.')
+ {
+ t = TokenId.RealLiteral;
+ NextChar();
+ ValidateDigit();
+ do
+ {
+ NextChar();
+ } while (Char.IsDigit(ch));
+ }
+ if (ch == 'E' || ch == 'e')
+ {
+ t = TokenId.RealLiteral;
+ NextChar();
+ if (ch == '+' || ch == '-') NextChar();
+ ValidateDigit();
+ do
+ {
+ NextChar();
+ } while (Char.IsDigit(ch));
+ }
+ if (ch == 'F' || ch == 'f') NextChar();
+ break;
+ }
+ if (textPos == textLen)
+ {
+ t = TokenId.End;
+ break;
+ }
+ throw ParseError(textPos, Res.InvalidCharacter, ch);
+ }
+ token.id = t;
+ token.text = text.Substring(tokenPos, textPos - tokenPos);
+ token.pos = tokenPos;
+ }
+
+ bool TokenIdentifierIs(string id)
+ {
+ return token.id == TokenId.Identifier && string.Equals(id, token.text, StringComparison.OrdinalIgnoreCase);
+ }
+
+ string GetIdentifier()
+ {
+ ValidateToken(TokenId.Identifier, Res.IdentifierExpected);
+ string id = token.text;
+ if (id.Length > 1 && id[0] == '@') id = id.Substring(1);
+ return id;
+ }
+
+ void ValidateDigit()
+ {
+ if (!Char.IsDigit(ch)) throw ParseError(textPos, Res.DigitExpected);
+ }
+
+ void ValidateToken(TokenId t, string errorMessage)
+ {
+ if (token.id != t) throw ParseError(errorMessage);
+ }
+
+ void ValidateToken(TokenId t)
+ {
+ if (token.id != t) throw ParseError(Res.SyntaxError);
+ }
+
+ Exception ParseError(string format, params object[] args)
+ {
+ return ParseError(token.pos, format, args);
+ }
+
+ Exception ParseError(int pos, string format, params object[] args)
+ {
+ return new ParseException(string.Format(System.Globalization.CultureInfo.CurrentCulture, format, args), pos);
+ }
+
+ static Dictionary CreateKeywords()
+ {
+ Dictionary d = new Dictionary(StringComparer.OrdinalIgnoreCase);
+ d.Add("true", trueLiteral);
+ d.Add("false", falseLiteral);
+ d.Add("null", nullLiteral);
+ d.Add(keywordIt, keywordIt);
+ d.Add(keywordIif, keywordIif);
+ d.Add(keywordNew, keywordNew);
+ foreach (Type type in predefinedTypes) d.Add(type.Name, type);
+ return d;
+ }
+ }
+
+ static class Res
+ {
+ public const string DuplicateIdentifier = "The identifier '{0}' was defined more than once";
+ public const string ExpressionTypeMismatch = "Expression of type '{0}' expected";
+ public const string ExpressionExpected = "Expression expected";
+ public const string InvalidCharacterLiteral = "Character literal must contain exactly one character";
+ public const string InvalidIntegerLiteral = "Invalid integer literal '{0}'";
+ public const string InvalidRealLiteral = "Invalid real literal '{0}'";
+ public const string UnknownIdentifier = "Unknown identifier '{0}'";
+ public const string NoItInScope = "No 'it' is in scope";
+ public const string IifRequiresThreeArgs = "The 'iif' function requires three arguments";
+ public const string FirstExprMustBeBool = "The first expression must be of type 'Boolean'";
+ public const string BothTypesConvertToOther = "Both of the types '{0}' and '{1}' convert to the other";
+ public const string NeitherTypeConvertsToOther = "Neither of the types '{0}' and '{1}' converts to the other";
+ public const string MissingAsClause = "Expression is missing an 'as' clause";
+ public const string ArgsIncompatibleWithLambda = "Argument list incompatible with lambda expression";
+ public const string TypeHasNoNullableForm = "Type '{0}' has no nullable form";
+ public const string NoMatchingConstructor = "No matching constructor in type '{0}'";
+ public const string AmbiguousConstructorInvocation = "Ambiguous invocation of '{0}' constructor";
+ public const string CannotConvertValue = "A value of type '{0}' cannot be converted to type '{1}'";
+ public const string NoApplicableMethod = "No applicable method '{0}' exists in type '{1}'";
+ public const string MethodsAreInaccessible = "Methods on type '{0}' are not accessible";
+ public const string MethodIsVoid = "Method '{0}' in type '{1}' does not return a value";
+ public const string AmbiguousMethodInvocation = "Ambiguous invocation of method '{0}' in type '{1}'";
+ public const string UnknownPropertyOrField = "No property or field '{0}' exists in type '{1}'";
+ public const string NoApplicableAggregate = "No applicable aggregate method '{0}' exists";
+ public const string CannotIndexMultiDimArray = "Indexing of multi-dimensional arrays is not supported";
+ public const string InvalidIndex = "Array index must be an integer expression";
+ public const string NoApplicableIndexer = "No applicable indexer exists in type '{0}'";
+ public const string AmbiguousIndexerInvocation = "Ambiguous invocation of indexer in type '{0}'";
+ public const string IncompatibleOperand = "Operator '{0}' incompatible with operand type '{1}'";
+ public const string IncompatibleOperands = "Operator '{0}' incompatible with operand types '{1}' and '{2}'";
+ public const string UnterminatedStringLiteral = "Unterminated string literal";
+ public const string InvalidCharacter = "Syntax error '{0}'";
+ public const string DigitExpected = "Digit expected";
+ public const string SyntaxError = "Syntax error";
+ public const string TokenExpected = "{0} expected";
+ public const string ParseExceptionFormat = "{0} (at index {1})";
+ public const string ColonExpected = "':' expected";
+ public const string OpenParenExpected = "'(' expected";
+ public const string CloseParenOrOperatorExpected = "')' or operator expected";
+ public const string CloseParenOrCommaExpected = "')' or ',' expected";
+ public const string DotOrOpenParenExpected = "'.' or '(' expected";
+ public const string OpenBracketExpected = "'[' expected";
+ public const string CloseBracketOrCommaExpected = "']' or ',' expected";
+ public const string IdentifierExpected = "Identifier expected";
+ }
+}
diff --git a/ams/Djy.Common/Interface/IDapperDBBase.cs b/ams/Djy.Common/Interface/IDapperDBBase.cs
index 334e454..d3b0bad 100644
--- a/ams/Djy.Common/Interface/IDapperDBBase.cs
+++ b/ams/Djy.Common/Interface/IDapperDBBase.cs
@@ -14,7 +14,7 @@ namespace Common.Repository.Interface
///
///
///
- IDbConnection GetConn();
+ IDbConnection GetConn(string type=null);
///
/// 无参数存储过程
///
diff --git a/ams/Djy.Common/Interface/IRepository.cs b/ams/Djy.Common/Interface/IRepository.cs
index 3001e31..e79f86d 100644
--- a/ams/Djy.Common/Interface/IRepository.cs
+++ b/ams/Djy.Common/Interface/IRepository.cs
@@ -12,8 +12,11 @@
// 仓储接口
// ***********************************************************************
+using Common.Repository.Core;
using Microsoft.EntityFrameworkCore;
using System;
+using System.Collections.Generic;
+using System.Data;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
@@ -89,4 +92,8 @@ namespace Common.Repository.Interface
#endregion
}
+
+
+
+
}
\ No newline at end of file
diff --git a/ams/djy.Model/Ams/AMS_Cntrno.cs b/ams/djy.Model/Ams/AMS_Cntrno.cs
index 7301c5b..0bd224e 100644
--- a/ams/djy.Model/Ams/AMS_Cntrno.cs
+++ b/ams/djy.Model/Ams/AMS_Cntrno.cs
@@ -1,11 +1,13 @@
using System;
using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace djy.Model.Ams
{
+ [Table("AMS_Cntrno")]
public class AMS_Cntrno
{
///
diff --git a/ams/djy.Model/Ams/AMS_House.cs b/ams/djy.Model/Ams/AMS_House.cs
index 7246540..aaada91 100644
--- a/ams/djy.Model/Ams/AMS_House.cs
+++ b/ams/djy.Model/Ams/AMS_House.cs
@@ -1,11 +1,13 @@
using System;
using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace djy.Model.Ams
{
+ [Table("AMS_House")]
public class AMS_House
{
///
diff --git a/ams/djy.Model/Ams/AMS_Master.cs b/ams/djy.Model/Ams/AMS_Master.cs
index d4bf998..a5b0562 100644
--- a/ams/djy.Model/Ams/AMS_Master.cs
+++ b/ams/djy.Model/Ams/AMS_Master.cs
@@ -1,12 +1,14 @@
using System;
using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace djy.Model.Ams
{
- public class AMSMaster
+ [Table("AMS_Master")]
+ public class AMS_Master
{
///
/// 主键
diff --git a/ams/djy.Model/AmsDto/AMSDto.cs b/ams/djy.Model/AmsDto/AMSDto.cs
index 5fed60e..8c43504 100644
--- a/ams/djy.Model/AmsDto/AMSDto.cs
+++ b/ams/djy.Model/AmsDto/AMSDto.cs
@@ -2,11 +2,9 @@
using System;
using System.Collections.Generic;
-namespace djy.Model.Ams
+namespace AMSDto
{
- public class AMSDto
- {
- }
+
public class AMSSaveDto
{
diff --git a/ams/djy.Paas.IService/Ams/IAms.cs b/ams/djy.Paas.IService/Ams/IAms.cs
deleted file mode 100644
index ae5fdac..0000000
--- a/ams/djy.Paas.IService/Ams/IAms.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using djy.Model.Ams;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace djy.IService.Ams
-{
- public interface IAms
- {
- void SaveInfo(AMSSaveDto Dto);
-
-
-
- }
-}
diff --git a/ams/djy.Paas.IService/Ams/IAmsService.cs b/ams/djy.Paas.IService/Ams/IAmsService.cs
new file mode 100644
index 0000000..4ebf59e
--- /dev/null
+++ b/ams/djy.Paas.IService/Ams/IAmsService.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using djy.Model;
+using Common;
+using AMSDto;
+
+namespace djy.Paas.IService
+{
+ ///
+ /// 账单中心模块
+ ///
+ public interface IAmsService:IsBase
+ {
+ ///
+ ///保存单据
+ ///
+ ///
+ public void SaveInfo(AMSSaveDto dto);
+
+
+ }
+}
diff --git a/ams/djy.paas.Service/Ams/AmsService.cs b/ams/djy.paas.Service/Ams/AmsService.cs
new file mode 100644
index 0000000..70c9459
--- /dev/null
+++ b/ams/djy.paas.Service/Ams/AmsService.cs
@@ -0,0 +1,43 @@
+using AMSDto;
+using djy.Paas.IService;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Dapper;
+using System.Data;
+using System.Data.SqlClient;
+using Common;
+using djy.Model.Ams;
+using Shared.Repository;
+
+namespace djy.Service.Ams
+{
+ ///
+ /// AMS
+ ///
+ public class AmsService : ServBase, IAmsService
+ {
+
+ DapperDBBase dapper = new DapperDBBase();
+ public async void SaveInfo(AMSSaveDto dto)
+ {
+
+
+ AMS_Master master = dto.MapTo();
+
+ using (var transaction = dapper.BeginTransaction(dapper.GetConn()))
+ {
+ master.CreateTime = DateTime.Now;
+ var gid = await dapper.InsertByEntityAsync(master);
+
+ transaction.Rollback();
+
+
+
+
+ }
+ }
+ }
+}
diff --git a/ams/djy.paas.Service/Ams/ServiceAms.cs b/ams/djy.paas.Service/Ams/ServiceAms.cs
deleted file mode 100644
index 6d588db..0000000
--- a/ams/djy.paas.Service/Ams/ServiceAms.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-using Common.Repository;
-using Common.Repository.Interface;
-using djy.IService.Ams;
-using djy.Model.Ams;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-
-namespace djy.Service.Ams
-{
- public class ServiceAms : IAms
- {
- private IDapperDBBase dapperDB;
- public void SaveInfo(AMSSaveDto Dto)
- {
-
-
-
-
- }
- }
-}
diff --git a/ams/djyweb_djyPaasApi/Controllers/ApiBase.cs b/ams/djy.paas.Service/Djy/ApiBase.cs
similarity index 96%
rename from ams/djyweb_djyPaasApi/Controllers/ApiBase.cs
rename to ams/djy.paas.Service/Djy/ApiBase.cs
index 423feed..03f9b76 100644
--- a/ams/djyweb_djyPaasApi/Controllers/ApiBase.cs
+++ b/ams/djy.paas.Service/Djy/ApiBase.cs
@@ -8,11 +8,9 @@ using System.Reflection;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using djy.Paas.IService;
-using Swashbuckle.AspNetCore.Swagger;
-using Swashbuckle.AspNetCore.SwaggerGen;
using djy.Model;
-namespace djy_AmsApi.Controllers
+namespace djy.Service
{
///
@@ -177,6 +175,17 @@ namespace djy_AmsApi.Controllers
///
protected string GetLoginName { get { return GetClaimsValue("loginname"); } }
+ ///
+ /// 获取登录公司名称
+ ///
+ protected string GetLoginComptName { get { return GetClaimsValue("COMNAME"); } }
+
+
+ ///
+ /// 获取登录公司id
+ ///
+ protected string GetLoginCompId { get { return GetClaimsValue("CompId"); } }
+
///
/// 获取登录类型
///
@@ -305,4 +314,7 @@ namespace djy_AmsApi.Controllers
}
+
+
+
}
diff --git a/ams/djy.paas.Service/Djy/AutoMapperExt.cs b/ams/djy.paas.Service/Djy/AutoMapperExt.cs
new file mode 100644
index 0000000..0be0a7e
--- /dev/null
+++ b/ams/djy.paas.Service/Djy/AutoMapperExt.cs
@@ -0,0 +1,74 @@
+// ***********************************************************************
+// Assembly : FairUtility
+// Author : Yubao Li
+// Created : 08-27-2015
+//
+// Last Modified By : Yubao Li
+// Last Modified On : 08-27-2015
+// ***********************************************************************
+//
+// Copyright (c) . All rights reserved.
+//
+//
+// ***********************************************************************
+
+using AutoMapper;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace djy.Service
+{
+ public static class AutoMapperExt
+ {
+ ///
+ /// 类型映射
+ ///
+ public static T MapTo(this object obj)
+ {
+ if (obj == null) return default(T);
+
+ var config = new MapperConfiguration(cfg => cfg.CreateMap(obj.GetType(), typeof(T)));
+ var mapper = config.CreateMapper();
+ return mapper.Map(obj);
+ }
+
+ ///
+ /// 集合列表类型映射
+ ///
+ public static List MapToList(this IEnumerable source)
+ {
+ Type sourceType = source.GetType().GetGenericArguments()[0]; //获取枚举的成员类型
+ var config = new MapperConfiguration(cfg => cfg.CreateMap(sourceType, typeof(TDestination)));
+ var mapper = config.CreateMapper();
+
+ return mapper.Map>(source);
+ }
+
+ ///
+ /// 集合列表类型映射
+ ///
+ public static List MapToList(this IEnumerable source)
+ {
+ var config = new MapperConfiguration(cfg => cfg.CreateMap(typeof(TSource), typeof(TDestination)));
+ var mapper = config.CreateMapper();
+
+ return mapper.Map>(source);
+ }
+
+ ///
+ /// 类型映射
+ ///
+ public static TDestination MapTo(this TSource source, TDestination destination)
+ where TSource : class
+ where TDestination : class
+ {
+ if (source == null) return destination;
+
+ var config = new MapperConfiguration(cfg => cfg.CreateMap(typeof(TSource), typeof(TDestination)));
+ var mapper = config.CreateMapper();
+ return mapper.Map(source);
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/ams/djy.paas.Service/Djy/DbContext.cs b/ams/djy.paas.Service/Djy/DbContext.cs
index 9bc9345..65172b1 100644
--- a/ams/djy.paas.Service/Djy/DbContext.cs
+++ b/ams/djy.paas.Service/Djy/DbContext.cs
@@ -9,6 +9,9 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Common;
+using System.Data;
+using Shared.Repository;
+
namespace djy.Service
{
///
@@ -27,7 +30,7 @@ namespace djy.Service
///
/// 账单中心库
///
- public const string BillCenter = "billcenter";
+ public const string AMSCenter = "AMS";
///
/// 日志库
///
@@ -44,8 +47,6 @@ namespace djy.Service
///
public static IdleBus DbBus=new IdleBus(TimeSpan.FromSeconds(20));
-
- //public static IFreeSql DbBus.Get(DbList.djypublicedb);
///
/// RedisDB
///
@@ -74,7 +75,6 @@ namespace djy.Service
else
{
DbBus.Register(item.SysKey, () => new FreeSqlBuilder().UseConnectionString((DataType)item.DataType, item.ConnString)
- // .UseAutoSyncStructure(sysOptionConfig.YsWebconfig.IsDev)
.UseAutoSyncStructure(false)
.UseNoneCommandParameter(true)
.UseMonitorCommand(cmd =>
@@ -90,17 +90,13 @@ namespace djy.Service
return true;
}
- /////
- ///// 数据库初始化
- /////
- //public static ReturnResult DbInit()
- //{
- // var rs = new ReturnResult();
- // DbBus.Get(DbList.djypublicedb).CodeFirst.SyncStructure();
- // DbBus.Get(DbList.djypublicedb).CodeFirst.SyncStructure();
- // rs.OK("生成成功!");
- // return rs;
- //}
+
+
+
+
+
+
+
}
}
diff --git a/ams/djy.paas.Service/Djy/ServBase.cs b/ams/djy.paas.Service/Djy/ServBase.cs
index 0df1f1c..9e4594e 100644
--- a/ams/djy.paas.Service/Djy/ServBase.cs
+++ b/ams/djy.paas.Service/Djy/ServBase.cs
@@ -122,7 +122,7 @@ namespace djy.Service
return count > 0 ? true : false;
}
-
+
}
diff --git a/ams/djyweb_djyPaasApi/Controllers/AMS/AmsController.cs b/ams/djyweb_djyPaasApi/Controllers/AMS/AmsController.cs
index e40e319..78c101e 100644
--- a/ams/djyweb_djyPaasApi/Controllers/AMS/AmsController.cs
+++ b/ams/djyweb_djyPaasApi/Controllers/AMS/AmsController.cs
@@ -1,24 +1,27 @@
-using Common;
-using Common.Repository.Interface;
-using djy.Model.Ams;
+using AMSDto;
+using Common;
+using djy.Service;
using djy.Service.Ams;
-
+using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System;
namespace djy_AmsApi.Controllers
{
- public class AmsController : ApiBase
- {
- private ServiceAms ams;
-
+ [AllowAnonymous]
+ public class AmsController : ApiBase
+ {
+
+ AmsService ser =new AmsService();
+
[HttpPost("Add")]
public Response Add(AMSSaveDto Dto)
{
var result = new Response();
try
{
- ams.Add(Dto);
+
+ ser.SaveInfo(Dto);
}
catch (Exception ex)
{
diff --git a/ams/djyweb_djyPaasApi/Startup.cs b/ams/djyweb_djyPaasApi/Startup.cs
index 6010a95..d6c0afd 100644
--- a/ams/djyweb_djyPaasApi/Startup.cs
+++ b/ams/djyweb_djyPaasApi/Startup.cs
@@ -18,6 +18,9 @@ using System.Net.Mime;
using AutoMapper;
using djy_AmsApi;
using djy.Service;
+using Common.Repository.Interface;
+using Shared.Repository;
+
namespace djy_AmsApi
{
@@ -71,7 +74,7 @@ namespace djy_AmsApi
}
//automapper
services.AddAutoMapper(typeof(AutoMapperConfig));
-
+
//
services.AddHangfire(config => {
config.UseRedisStorage(sysOptionConfig.YsWebconfig.Redis, new Hangfire.Redis.RedisStorageOptions { Prefix = "hf_"+sysOptionConfig.YsWebconfig.WebName,InvisibilityTimeout=TimeSpan.FromHours(1) });
@@ -98,8 +101,8 @@ namespace djy_AmsApi
x.UseDashboard();
});
}
-
-
+
+
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "djy_AmsApi", Version = "v1" });
diff --git a/ams/djyweb_djyPaasApi/appsettings.Development.json b/ams/djyweb_djyPaasApi/appsettings.Development.json
index 04ac6dc..83130dc 100644
--- a/ams/djyweb_djyPaasApi/appsettings.Development.json
+++ b/ams/djyweb_djyPaasApi/appsettings.Development.json
@@ -28,13 +28,14 @@
"Rbmq_UserName": "djy_paas",
"Rbmq_Password": "123qwe",
"Rbmq_Sqlhost": "Data Source =192.168.1.205,1433; Initial Catalog=TestDjyLogs; Persist Security Info=True; User ID =test; Password=test123;pooling=true",
+ "DapperDbString": "Data Source =123.234.225.158,28000; Initial Catalog=DevAMS; Persist Security Info=True; User ID =dev; Password=dev123;pooling=true;max pool size=2",
"DataConnList": [
{
"SysKey": "AMS",
- "TitleName": "账单数据库",
+ "TitleName": "AMS",
"Index": 100,
"DataType": 1,
"Status": 0,
diff --git a/ams/djyweb_djyPaasApi/appsettings.Prod.json b/ams/djyweb_djyPaasApi/appsettings.Prod.json
index 84d9606..1e23902 100644
--- a/ams/djyweb_djyPaasApi/appsettings.Prod.json
+++ b/ams/djyweb_djyPaasApi/appsettings.Prod.json
@@ -27,17 +27,17 @@
"Rbmq_UserName": "admin",
"Rbmq_Password": "admin",
"Rbmq_Sqlhost": "Data Source =172.31.85.154; Initial Catalog=djy_logs; Persist Security Info=True; User ID =sa; Password=QDdjy#2020*;pooling=true",
+ "DapperDbString": "Data Source =123.234.225.158,28000; Initial Catalog=DevAMS; Persist Security Info=True; User ID =dev; Password=dev123;pooling=true;max pool size=2",
"DataConnList": [
{
- "SysKey": "billcenter",
+ "SysKey": "AMS",
- "TitleName": "账单数据库",
+ "TitleName": "AMS",
"Index": 100,
"DataType": 1,
"Status": 0,
- "ConnString": "Data Source =172.31.85.154; Initial Catalog=BillCenter; Persist Security Info=True; User ID =sa; Password=QDdjy#2020*;pooling=true;max pool size=2"
-
+ "ConnString": "Data Source =123.234.225.158,28000; Initial Catalog=DevAMS; Persist Security Info=True; User ID =dev; Password=dev123;pooling=true;max pool size=2"
},
{
"SysKey": "djydb",
diff --git a/ams/djyweb_djyPaasApi/appsettings.json b/ams/djyweb_djyPaasApi/appsettings.json
index 8f3b4f0..6ef5ecb 100644
--- a/ams/djyweb_djyPaasApi/appsettings.json
+++ b/ams/djyweb_djyPaasApi/appsettings.json
@@ -27,17 +27,16 @@
"Rbmq_UserName": "admin",
"Rbmq_Password": "admin",
"Rbmq_Sqlhost": "Data Source =172.31.85.154; Initial Catalog=djy_logs; Persist Security Info=True; User ID =sa; Password=QDdjy#2020*;pooling=true",
+ "DapperDbString": "Data Source =123.234.225.158,28000; Initial Catalog=DevAMS; Persist Security Info=True; User ID =dev; Password=dev123;pooling=true;max pool size=2",
"DataConnList": [
{
- "SysKey": "billcenter",
-
- "TitleName": "账单数据库",
+ "SysKey": "AMS",
+ "TitleName": "AMS",
"Index": 100,
"DataType": 1,
"Status": 0,
- "ConnString": "Data Source =172.31.85.154; Initial Catalog=BillCenter; Persist Security Info=True; User ID =sa; Password=QDdjy#2020*;pooling=true;max pool size=2"
-
+ "ConnString": "Data Source =123.234.225.158,28000; Initial Catalog=DevAMS; Persist Security Info=True; User ID =dev; Password=dev123;pooling=true;max pool size=2"
},
{
"SysKey": "djydb",
@@ -46,8 +45,6 @@
"Index": 100,
"DataType": 1,
"Status": 0,
- // "ConnString": "Data Source =172.17.0.3; Initial Catalog=djy_PaasData; Persist Security Info=True; User ID =sa; Password=QDdjy2021*;pooling=true",
- //"ConnString": "Data Source =djypaas.myshipping.net,5099; Initial Catalog=djy_PubliceData; Persist Security Info=True; User ID =sa; Password=QDdjy#2020*;pooling=true""ConnString": "Data Source =djypaas.myshipping.net,5099; Initial Catalog=djy_PubliceData; Persist Security Info=True; User ID =sa; Password=QDdjy#2020*;pooling=true"
"ConnString": "Data Source =172.31.85.154,1433; Initial Catalog=djy_PubliceData; Persist Security Info=True; User ID =sa; Password=QDdjy#2020*;pooling=true"
},
@@ -57,8 +54,6 @@
"Index": 100,
"DataType": 1,
"Status": 0,
- // "ConnString": "Data Source =172.17.0.3; Initial Catalog=djy_logs; Persist Security Info=True; User ID = sa; Password=QDdjy2021*;pooling=true",
- //"ConnString": "Data Source =djypaas.myshipping.net,5099; Initial Catalog=djy_logs; Persist Security Info=True; User ID =sa; Password=QDdjy#2020*;pooling=true"
"ConnString": "Data Source =172.31.85.154,1433; Initial Catalog=djy_logs; Persist Security Info=True; User ID =sa; Password=QDdjy#2020*;pooling=true"
},
@@ -69,9 +64,6 @@
"Index": 100,
"DataType": 1,
"Status": 0,
- // "ConnString": "Data Source =172.17.0.3; Initial Catalog=MYSHIPPINGTEST8; Persist Security Info=True; User ID =sa; Password=QDdjy2021*;pooling=true",
- //"ConnString": "Data Source =172.31.85.154; Initial Catalog=MYSHIPPINGTEST8; Persist Security Info=True; User ID =sa; Password=QDdjy#2020*;pooling=true",
- //"ConnString": "Data Source =djypaas.myshipping.net,5099; Initial Catalog=DsPingTai; Persist Security Info=True; User ID =sa; Password=QDdjy#2020*;pooling=true",
"ConnString": "Data Source =172.31.85.154,1433; Initial Catalog=DsPingTai; Persist Security Info=True; User ID =sa; Password=QDdjy#2020*;pooling=true"
}