123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361 |
- using Ant.Core;
- using Ant.Core.Visitors;
- using Ant.Data;
- using Ant.DbExpressions;
- using Ant.Descriptors;
- using Ant.Entity;
- using Ant.Exceptions;
- using Ant.Infrastructure;
- using Ant.ORM;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Linq.Expressions;
- using System.Reflection;
- using System.Text;
- namespace Ant.Oracle
- {
- /// <summary>
- /// Oracle数据库
- /// </summary>
- public class OracleContext : DbContext
- {
- DbContextServiceProvider _dbContextServiceProvider;
- bool _convertToUppercase = true;
-
- /// <summary>
- ///
- /// </summary>
- /// <param name="dbConnectionFactory"></param>
- public OracleContext(string dbConnectionFactory)
- {
- Utils.CheckNull(dbConnectionFactory);
- this._dbContextServiceProvider = new DbContextServiceProvider(ConvertToUppercase);
- }
- /// <summary>
- ///
- /// </summary>
- public bool ConvertToUppercase { get { return this._convertToUppercase; } set { this._convertToUppercase = value; } }
- /// <summary>
- ///
- /// </summary>
- public override IDbContextServiceProvider DbContextServiceProvider
- {
- get { return this._dbContextServiceProvider; }
- }
- /// <summary>
- ///
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="entity"></param>
- /// <returns></returns>
- public override T Insert<T>(T entity)
- {
- Utils.CheckNull(entity);
- TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(entity.GetType());
- EnsureMappingTypeHasPrimaryKey(typeDescriptor);
- MappingMemberDescriptor keyMemberDescriptor = typeDescriptor.PrimaryKey;
- MemberInfo keyMember = typeDescriptor.PrimaryKey.MemberInfo;
- object keyValue = null;
- string sequenceName;
- object sequenceValue = null;
- MappingMemberDescriptor defineSequenceMemberDescriptor = GetDefineSequenceMemberDescriptor(typeDescriptor, out sequenceName);
- if (defineSequenceMemberDescriptor != null)
- {
- sequenceValue = ConvertIdentityType(this.GetSequenceNextValue(sequenceName), defineSequenceMemberDescriptor.MemberInfoType);
- }
- Dictionary<MappingMemberDescriptor, DbExpression> insertColumns = new Dictionary<MappingMemberDescriptor, DbExpression>();
- foreach (var kv in typeDescriptor.MappingMemberDescriptors)
- {
- MemberInfo member = kv.Key;
- MappingMemberDescriptor memberDescriptor = kv.Value;
- object val = null;
- if (defineSequenceMemberDescriptor != null && memberDescriptor == defineSequenceMemberDescriptor)
- {
- val = sequenceValue;
- }
- else
- val = memberDescriptor.GetValue(entity);
- if (memberDescriptor == keyMemberDescriptor)
- {
- keyValue = val;
- }
- DbExpression valExp = DbExpression.Parameter(val, memberDescriptor.MemberInfoType);
- insertColumns.Add(memberDescriptor, valExp);
- }
- if (keyValue == null)
- {
- throw new ChloeException(string.Format("The primary key '{0}' could not be null.", keyMemberDescriptor.MemberInfo.Name));
- }
- DbInsertExpression e = new DbInsertExpression(typeDescriptor.Table);
- foreach (var kv in insertColumns)
- {
- e.InsertColumns.Add(kv.Key.Column, kv.Value);
- }
- this.ExecuteSqlCommand(e);
- if (defineSequenceMemberDescriptor != null)
- defineSequenceMemberDescriptor.SetValue(entity, sequenceValue);
- return entity;
- }
- public override object Insert<T>(Expression<Func<T>> body)
- {
- Utils.CheckNull(body);
- TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(typeof(T));
- EnsureMappingTypeHasPrimaryKey(typeDescriptor);
- MappingMemberDescriptor keyMemberDescriptor = typeDescriptor.PrimaryKey;
- string sequenceName;
- object sequenceValue = null;
- MappingMemberDescriptor defineSequenceMemberDescriptor = GetDefineSequenceMemberDescriptor(typeDescriptor, out sequenceName);
- Dictionary<MemberInfo, Expression> insertColumns = InitMemberExtractor.Extract(body);
- DbInsertExpression e = new DbInsertExpression(typeDescriptor.Table);
- object keyVal = null;
- foreach (var kv in insertColumns)
- {
- MemberInfo key = kv.Key;
- MappingMemberDescriptor memberDescriptor = typeDescriptor.TryGetMappingMemberDescriptor(key);
- if (memberDescriptor == null)
- throw new ChloeException(string.Format("The member '{0}' does not map any column.", key.Name));
- if (memberDescriptor == defineSequenceMemberDescriptor)
- throw new ChloeException(string.Format("Can not insert value into the column '{0}',because it's mapping member has define a sequence.", memberDescriptor.Column.Name));
- if (memberDescriptor.IsPrimaryKey)
- {
- object val = ExpressionEvaluator.Evaluate(kv.Value);
- if (val == null)
- throw new ChloeException(string.Format("The primary key '{0}' could not be null.", memberDescriptor.MemberInfo.Name));
- else
- {
- keyVal = val;
- e.InsertColumns.Add(memberDescriptor.Column, DbExpression.Parameter(keyVal));
- continue;
- }
- }
- e.InsertColumns.Add(memberDescriptor.Column, typeDescriptor.Visitor.Visit(kv.Value));
- }
- if (keyMemberDescriptor == defineSequenceMemberDescriptor)
- {
- sequenceValue = ConvertIdentityType(this.GetSequenceNextValue(sequenceName), defineSequenceMemberDescriptor.MemberInfoType);
- keyVal = sequenceValue;
- e.InsertColumns.Add(keyMemberDescriptor.Column, DbExpression.Parameter(keyVal));
- }
- if (keyVal == null)
- {
- throw new ChloeException(string.Format("The primary key '{0}' could not be null.", keyMemberDescriptor.MemberInfo.Name));
- }
- this.ExecuteSqlCommand(e);
- return keyVal;
- }
- public override int Update<T>(T entity)
- {
- Utils.CheckNull(entity);
- TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(entity.GetType());
- EnsureMappingTypeHasPrimaryKey(typeDescriptor);
- MappingMemberDescriptor keyMemberDescriptor = typeDescriptor.PrimaryKey;
- MemberInfo keyMember = keyMemberDescriptor.MemberInfo;
- object keyVal = null;
- IEntityState entityState = this.TryGetTrackedEntityState(entity);
- Dictionary<MappingMemberDescriptor, DbExpression> updateColumns = new Dictionary<MappingMemberDescriptor, DbExpression>();
- foreach (var kv in typeDescriptor.MappingMemberDescriptors)
- {
- MemberInfo member = kv.Key;
- MappingMemberDescriptor memberDescriptor = kv.Value;
- if (member == keyMember)
- {
- keyVal = memberDescriptor.GetValue(entity);
- keyMemberDescriptor = memberDescriptor;
- continue;
- }
- SequenceAttribute attr = (SequenceAttribute)memberDescriptor.GetCustomAttribute(typeof(SequenceAttribute));
- if (attr != null)
- continue;
- object val = memberDescriptor.GetValue(entity);
- if (entityState != null && !entityState.HasChanged(memberDescriptor, val))
- continue;
- DbExpression valExp = DbExpression.Parameter(val, memberDescriptor.MemberInfoType);
- updateColumns.Add(memberDescriptor, valExp);
- }
- if (keyVal == null)
- throw new ChloeException(string.Format("The primary key '{0}' could not be null.", keyMember.Name));
- if (updateColumns.Count == 0)
- return 0;
- DbExpression left = new DbColumnAccessExpression(typeDescriptor.Table, keyMemberDescriptor.Column);
- DbExpression right = DbExpression.Parameter(keyVal, keyMemberDescriptor.MemberInfoType);
- DbExpression conditionExp = new DbEqualExpression(left, right);
- DbUpdateExpression e = new DbUpdateExpression(typeDescriptor.Table, conditionExp);
- foreach (var item in updateColumns)
- {
- e.UpdateColumns.Add(item.Key.Column, item.Value);
- }
- int ret = this.ExecuteSqlCommand(e);
- if (entityState != null)
- entityState.Refresh();
- return ret;
- }
- public override int Update<T>(Expression<Func<T, T>> body, Expression<Func<T, bool>> condition)
- {
- Utils.CheckNull(body);
- Utils.CheckNull(condition);
- TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(typeof(T));
- Dictionary<MemberInfo, Expression> updateColumns = InitMemberExtractor.Extract(body);
- DbExpression conditionExp = typeDescriptor.Visitor.VisitFilterPredicate(condition);
- DbUpdateExpression e = new DbUpdateExpression(typeDescriptor.Table, conditionExp);
- foreach (var kv in updateColumns)
- {
- MemberInfo key = kv.Key;
- MappingMemberDescriptor memberDescriptor = typeDescriptor.TryGetMappingMemberDescriptor(key);
- if (memberDescriptor == null)
- throw new ChloeException(string.Format("The member '{0}' does not map any column.", key.Name));
- if (memberDescriptor.IsPrimaryKey)
- throw new ChloeException(string.Format("Could not update the primary key '{0}'.", memberDescriptor.Column.Name));
- SequenceAttribute attr = (SequenceAttribute)memberDescriptor.GetCustomAttribute(typeof(SequenceAttribute));
- if (attr != null)
- throw new ChloeException(string.Format("Could not update the column '{0}',because it's mapping member has define a sequence.", memberDescriptor.Column.Name));
- e.UpdateColumns.Add(memberDescriptor.Column, typeDescriptor.Visitor.Visit(kv.Value));
- }
- if (e.UpdateColumns.Count == 0)
- return 0;
- return this.ExecuteSqlCommand(e);
- }
- int ExecuteSqlCommand(DbExpression e)
- {
- IDbExpressionTranslator translator = this.DbContextServiceProvider.CreateDbExpressionTranslator();
- List<DbParam> parameters;
- string cmdText = translator.Translate(e, out parameters);
- int r = this.db.ExecuteNonQuery(cmdText, parameters.ToArray());
- return r;
- }
- object GetSequenceNextValue(string sequenceName)
- {
- if (this.ConvertToUppercase)
- sequenceName = sequenceName.ToUpper();
- object ret = this.db.ExecuteScalar(string.Concat("SELECT \"", sequenceName, "\".\"NEXTVAL\" FROM \"DUAL\""));
- if (ret == null || ret == DBNull.Value)
- {
- throw new ChloeException(string.Format("Unable to get the sequence '{0}' next value.", sequenceName));
- }
- return ret;
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="typeDescriptor"></param>
- /// <param name="sequenceName"></param>
- /// <returns></returns>
- static MappingMemberDescriptor GetDefineSequenceMemberDescriptor(TypeDescriptor typeDescriptor, out string sequenceName)
- {
- sequenceName = null;
- MappingMemberDescriptor defineSequenceMemberDescriptor = null;
- foreach (MappingMemberDescriptor memberDescriptor in typeDescriptor.MappingMemberDescriptors.Values)
- {
- SequenceAttribute attr = (SequenceAttribute)memberDescriptor.GetCustomAttribute(typeof(SequenceAttribute));
- if (attr != null)
- {
- if (defineSequenceMemberDescriptor != null)
- {
- throw new ChloeException(string.Format("映射类型'{0}'不能确定身份的多个成员。", typeDescriptor.EntityType.FullName));
- //throw new ChloeException(string.Format("Mapping type '{0}' can not define multiple identity members.", typeDescriptor.EntityType.FullName));
- }
- if (string.IsNullOrEmpty(attr.Name))
- {
- throw new ChloeException("序列名称不能为空。");
- //throw new ChloeException("Sequence name can not be empty.");
- }
-
- sequenceName = attr.Name;
- defineSequenceMemberDescriptor = memberDescriptor;
- }
- }
- if (defineSequenceMemberDescriptor != null)
- EnsureDefineSequenceMemberType(defineSequenceMemberDescriptor);
- return defineSequenceMemberDescriptor;
- }
- static void EnsureDefineSequenceMemberType(MappingMemberDescriptor defineSequenceMemberDescriptor)
- {
- if (defineSequenceMemberDescriptor.MemberInfoType != UtilConstants.TypeOfInt16 && defineSequenceMemberDescriptor.MemberInfoType != UtilConstants.TypeOfInt32 && defineSequenceMemberDescriptor.MemberInfoType != UtilConstants.TypeOfInt64)
- {
- throw new ChloeException("Identity type must be Int16,Int32 or Int64.");
- }
- }
- static void EnsureMappingTypeHasPrimaryKey(TypeDescriptor typeDescriptor)
- {
- if (!typeDescriptor.HasPrimaryKey())
- throw new ChloeException(string.Format("Mapping type '{0}' does not define a primary key.", typeDescriptor.EntityType.FullName));
- }
- static object ConvertIdentityType(object identity, Type conversionType)
- {
- if (identity.GetType() != conversionType)
- return Convert.ChangeType(identity, conversionType);
- return identity;
- }
- }
- }
|