private void Import(Type typeMapping, Action<ExecuteEventArgs> executing, Action<ExecuteEventArgs> onStart, Action<ExecuteEventArgs> onEnd, string tag, Where where, IEnumerable<XElement> q) { #region init Connection connection = null; Unimake.ETL.Destination.ObjectDestination destination = null; foreach(var el in q) { if(Ignore(el)) continue; try { connection = DbContext.CreateConnection(); #region init IParentModel model = null; string TDestination = GetAttribute(el, "type"); #endregion #region source string query = el.Element("Query").Value.ToString(); //aqui iremos assumir que sempre terá o [[where]] se não tiver, sem problemas string w = ""; string v = ""; if(where != null) { w = where.ToString(); //também temos o @value, que sempre será informado, logo, temos que substituir o @value, por algum valor. //este vem informado no parameters do Where if(where.Parameters.Contains("@value")) v = Unimake.Convert.ToString(where.Parameters["@value"].Value); } query = query.Replace("[[where]]", w); query = query.Replace("@value", v); Source = new Unimake.ETL.Source.SqlSource(Connection); ((Unimake.ETL.Source.SqlSource)Source).FromQuery(query); #endregion #region destination if(String.IsNullOrEmpty(TDestination)) throw new ArgumentNullException("type", "O atributo \"type\" é requerido para o tipo \"" + el.Name + "\" dentro do XML."); destination = new Unimake.ETL.Destination.ObjectDestination(); destination.SetObjectResult(Activator.CreateInstance(Unimake.Convert.ToType(TDestination))); #endregion #region transform Transform = new Unimake.ETL.Transform.Transform(Source, destination); var mappings = el.Elements("MappingKey"); MappingKeys = (from x in mappings.Elements() select ToMappingKey(x)) .ToList(); foreach(MappingKey item in MappingKeys) { Transform.Map(item.From, item.To, item.ToFunc()); } #endregion #region execute destination.ProcessWithAction((s, r) => { model = s as IParentModel; //------------------------------------------------------------------------- // Pesquisar e validar se existe //------------------------------------------------------------------------- string table = model.GetTableName(); string sql = String.Format("SELECT GUID FROM {0} WHERE EGUID = @p1", table); IList<Parameter> parameters = new List<Parameter>(); parameters.Add(new Parameter { ParameterName = "@p1", Value = model.EGUID }); if(Settings.Tables[table].Fields.Contains("Excluido")) { sql += String.Format(" AND Excluido = @p2", table); parameters.Add(new Parameter { ParameterName = "@p2", Value = Excluido.Nao }); } DataReader dr = DbContext.ExecuteReader(sql, parameters); model.New = !dr.HasRows; if(dr.Read()) model.GUID = dr.GetString("GUID"); model.Save(); executing(new ExecuteEventArgs { Message = String.Format("O objeto identificado como {0} de código {1} foi salvo na base de dados.", model.GUID, model.EGUID), }); Thread.Sleep(0); }); Transform.OnRowError((row, op, ex) => { executing(new ExecuteEventArgs { Success = false, Exception = ex, CurrentObject = model }); }); Transform.OnStart((t) => { onStart(new ExecuteEventArgs { Message = String.Format("Iniciando a carga do tipo {0}", TDestination) }); }); Transform.OnComplete((t) => { onEnd(new ExecuteEventArgs { Message = String.Format("Concluído a carga do tipo {0}", TDestination) }); }); Destination = destination; Transform.Execute(); #endregion } catch(Exception ex) { executing(new ExecuteEventArgs { CurrentObject = destination.ObjectResult as IParentModel, Exception = ex, Message = ex.Message, Success = false }); } finally { Connection.Dispose(); if(connection != null) { connection.Dispose(); } } } }
private void Export(Type typeMapping, Action<ExecuteEventArgs> executing, Action<ExecuteEventArgs> onStart, Action<ExecuteEventArgs> onEnd, string tag, Where where, IEnumerable<XElement> q) { foreach(var el in q) { if(Ignore(el)) continue; try { #region init IParentModel model = null; string methodName = GetAttribute(el, "Method"); //Aqui, se o método for o padrão, iremos passar o caminho do namespace completo, //pois devemos usar o GenerateXML deste ETL. if(methodName.Equals("GenerateXML", StringComparison.InvariantCultureIgnoreCase)) { methodName = "Unimake.ETL.IGenerateFile.GenerateXML"; } string fileNameTemplate = GetAttribute(el, "FileName"); #endregion #region source Source = new Unimake.ETL.Source.ObjectSource(); #endregion #region destination string TDestination = el.Name.LocalName; Unimake.ETL.Destination.CustomDestination destination = new Unimake.ETL.Destination.CustomDestination(); #endregion #region transform Transform = new Unimake.ETL.Transform.Transform(Source, destination); var mappings = el.Elements("MappingKey"); MappingKeys = (from x in mappings.Elements() select ToMappingKey(x)) .ToList(); foreach(MappingKey item in MappingKeys) { //------------------------------------------------------------------------- // Neste caso, como é de objeto, o from sempre será value //------------------------------------------------------------------------- item.From = "value"; Transform.Map(item.From, item.To); item.Where = where; ((Unimake.ETL.Source.ObjectSource)Source).WithRowAction(ToIEnumerable(item.ToIEnumerableFunc())); } #endregion #region execute destination.ProcessWithAction((r) => { model = r["valueRows"] as IParentModel; string fileName = fileNameTemplate; if(fileName.IsNullOrEmpty()) { //não encontrou a propriedade "FileName", então vamos ver se existe o método "GetFileName" var m = el.Elements("GetFileName"); if(m == null) throw new NotImplementedException("Filename property or GetFileName method was not defined."); fileName = GetFileName(m.First().Value, model); } else fileName = fileName.Replace("{GUID}", Guid.NewGuid().ToString()); MethodInfo mi = model.GetType().GetMethods(BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.NonPublic | BindingFlags.Public) .FirstOrDefault(w => w.Name == methodName); if(mi == null) executing(new ExecuteEventArgs { Message = String.Format("O objeto identificado como {0} de código {1} não possui o método {2}.", model.GUID, model.EGUID, methodName), }); else { //------------------------------------------------------------------------- // Aqui vamos assumir que os métodos retornam sempre um XML // com o tempo vamos melhorar este processo //------------------------------------------------------------------------- XmlDocument doc = mi.Invoke(model, null) as XmlDocument; fileName = String.Format(fileName, 1, DateTime.Now); doc.Save(fileName); executing(new ExecuteEventArgs { Message = String.Format("O objeto identificado como {0} de código {1} exportado para o arquivo {2}.", model.GUID, model.EGUID, fileName), }); } Thread.Sleep(0); }); Transform.OnRowError((row, op, ex) => { executing(new ExecuteEventArgs { Success = false, Exception = ex, CurrentObject = model }); }); Transform.OnStart((t) => { onStart(new ExecuteEventArgs { Message = String.Format("Iniciando a carga do tipo {0}", TDestination) }); }); Transform.OnComplete((t) => { onEnd(new ExecuteEventArgs { Message = String.Format("Concluído a carga do tipo {0}", TDestination) }); }); Destination = destination; Transform.Execute(); #endregion } catch(Exception ex) { executing(new ExecuteEventArgs { Exception = ex, Message = ex.Message, Success = false }); } finally { Connection.Dispose(); } } }