/// <summary>
        /// Identity stage II: update EdgeObject DB (staging) with edge object from Delivery DB
        /// using LOCK on EdgeObject table:
        /// * sync last changes according transform timestamp
        /// * update modified EdgeObjects --> IdentityStatus = Modified
        /// * insert new EdgeObjects --> IdentityStatus = New
        /// </summary>
        public void UpdateEdgeObjects()
        {
            _config = String.IsNullOrEmpty(ConfigXml) ? new IdentityConfig() : IdentityConfig.Deserialize(ConfigXml);

            // load object dependencies
            Dependencies = EdgeObjectConfigLoader.GetEdgeObjectDependencies(AccountId, _objectsSqlConnection).Values.ToList();
            Log("UpdateEdgeObjects:: EdgeObjects dependencies loaded");

            int maxDependecyDepth = Dependencies.Max(x => x.Depth);

            for (int i = 0; i <= maxDependecyDepth; i++)
            {
                var currentDepth = i;
                Log(String.Format("UpdateEdgeObjects:: dependency depth={0}", currentDepth));

                foreach (var field in Dependencies.Where(x => x.Depth == currentDepth))
                {
                    Log(String.Format("UpdateEdgeObjects:: starting update field '{0}' of type '{1}'", field.Field.Name, field.Field.FieldEdgeType.Name));
                    UpdateObjectDependencies(field.Field.FieldEdgeType);

                    if (_config.UpdateExistingObjects && DeliveryContainsChanges(field.Field.FieldEdgeType, IdentityStatus.Unchanged, true))
                    {
                        Log(String.Format("UpdateEdgeObjects:: delivery contains changes of {0}, starting sync", field.Field.Name));

                        SyncLastChangesWithLock(field.Field.FieldEdgeType);

                        if (DeliveryContainsChanges(field.Field.FieldEdgeType, IdentityStatus.Modified))
                        {
                            UpdateExistingEdgeObjectsByDelivery(field.Field.FieldEdgeType);
                            Log(String.Format("UpdateEdgeObjects:: update modified object of type '{0}'", field.Field.FieldEdgeType));
                        }

                        if (_config.CreateNewObjects && DeliveryContainsChanges(field.Field.FieldEdgeType, IdentityStatus.New))
                        {
                            InsertNewEdgeObjects(field.Field.FieldEdgeType);
                            Log(String.Format("UpdateEdgeObjects:: insert new objects of type '{0}'", field.Field.FieldEdgeType));
                        }
                    }
                    else
                    {
                        Log(String.Format("UpdateEdgeObjects:: delivery doen't contain changes of {0}, nothing to sync", field.Field.Name));
                    }

                    CreateTempDeliveryGkTkTable(field.Field.FieldEdgeType);
                }
            }
        }
예제 #2
0
        /// <summary>
        /// Build Metics SELECT from Delivery Metrics table with JOINs all delivery objects by TKs
        /// in order to fill Staging Metrics table found by Best Match from Delivery Metrics table
        /// </summary>
        public static string GetMetricsView(int accountId, string tableName, SqlConnection connection)
        {
            var selectStr   = String.Empty;
            var fromStr     = String.Format("\t[EdgeDeliveries].{0} AS Metrics\n", tableName);
            var tablePrefix = tableName.ToLower().Replace("_metrics]", "").Replace("[dbo].[", "");

            var edgeTypes = EdgeObjectConfigLoader.LoadEdgeTypes(accountId, connection);
            var sql       = String.Format("SELECT EdgeFieldName, ParentFieldName, EdgeTypeID, MeasureName FROM [EdgeDeliveries].[dbo].[MD_MetricsMetadata] WHERE TABLENAME='{0}'", tableName);

            using (var cmd = new SqlCommand(sql, connection))
            {
                using (var reader = cmd.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        // add dimension field (JOIN according TK to find GK and WHERE by type ID)
                        if (!String.IsNullOrEmpty(reader["EdgeFieldName"].ToString()))
                        {
                            var edgeType = edgeTypes.Values.FirstOrDefault(x => x.TypeID == int.Parse(reader["EdgeTypeID"].ToString()));
                            if (edgeType == null)
                            {
                                continue;
                            }

                            var fieldName       = reader["EdgeFieldName"].ToString().Replace("_gk", "");
                            var parentFieldName = reader["ParentFieldName"].ToString().Replace("_gk", "");

                            selectStr = String.Format("{0}\t{1}.GK AS {1}_gk,\n", selectStr, fieldName);
                            fromStr   = String.Format("{0}\tINNER JOIN {1} AS {3} ON Metrics.{2}_tk={3}.TK\n",
                                                      fromStr, GetTableName(tablePrefix, edgeType.TableName), parentFieldName, fieldName);
                        }
                        // add measure fields
                        else if (!String.IsNullOrEmpty(reader["MeasureName"].ToString()))
                        {
                            selectStr = String.Format("{0}\tMetrics.{1},\n", selectStr, reader["MeasureName"]);
                        }
                    }
                }
            }
            // combine select
            return(selectStr.Length == 0 ?
                   "No data relevant data in MD_MetricsMetadata" :
                   String.Format("SELECT\n{0}\nFROM\n{1}", selectStr.Remove(selectStr.Length - 2, 2), fromStr));
        }
        /// <summary>
        /// Identity stage I: update delivery objects with existing in EdgeObject DB object GKs
        /// tag Delivery objects by IdentityStatus (New, Modified or Unchanged)
        /// </summary>
        public void IdentifyDeliveryObjects()
        {
            // load object dependencies
            Dependencies = EdgeObjectConfigLoader.GetEdgeObjectDependencies(AccountId, _objectsSqlConnection).Values.ToList();
            Log("IdentifyDeliveryObjects:: EdgeObjects dependencies loaded");

            var maxDependecyDepth = Dependencies.Max(x => x.Depth);
            var updatedTypes      = new List <EdgeType>();

            for (var i = 0; i <= maxDependecyDepth; i++)
            {
                var currentDepth = i;
                Log(String.Format("IdentifyDeliveryObjects:: dependency depth={0}", currentDepth));

                foreach (var field in Dependencies.Where(x => x.Depth == currentDepth))
                {
                    Log(String.Format("IdentifyDeliveryObjects:: starting identify field '{0}' of type '{1}'", field.Field.Name, field.Field.FieldEdgeType.Name));

                    // nothing to do if field of the same type was already updated
                    if (updatedTypes.Contains(field.Field.FieldEdgeType))
                    {
                        Log(String.Format("IdentifyDeliveryObjects:: nothing to Identify for field '{0}', type '{1}' was already identified", field.Field.Name, field.Field.FieldEdgeType.Name));
                        continue;
                    }

                    Log(String.Format("IdentifyDeliveryObjects:: update '{0}' type dependencies", field.Field.FieldEdgeType.Name));
                    UpdateObjectDependencies(field.Field.FieldEdgeType);

                    Log(String.Format("IdentifyDeliveryObjects:: Create Temp Objects table for type '{0}'", field.Field.FieldEdgeType.Name));
                    CreateTempObjectsTable(field.Field.FieldEdgeType);

                    Log(String.Format("IdentifyDeliveryObjects:: Set delivery objects identity (GK) for type '{0}'", field.Field.FieldEdgeType.Name));
                    SetIdentity(field.Field.FieldEdgeType);

                    Log(String.Format("IdentifyDeliveryObjects:: Create Temp Delivery GK-TK table for type '{0}'", field.Field.FieldEdgeType.Name));
                    CreateTempDeliveryGkTkTable(field.Field.FieldEdgeType);

                    Log(String.Format("IdentifyDeliveryObjects:: Finished identify type '{0}'", field.Field.FieldEdgeType.Name));
                    updatedTypes.Add(field.Field.FieldEdgeType);
                }
            }
        }
        /// <summary>
        /// Before searching for object GKs update all GK of its parent fields
        /// (objects it depends on)
        /// For example: before searching for AdGroup GKs, update all AdGroup Campaings
        /// </summary>
        private void UpdateObjectDependencies(EdgeType edgeType)
        {
            // nothitng to do if there are no GK to update
            if (edgeType.Fields.All(x => x.Field.FieldEdgeType == null))
            {
                return;
            }

            var mainTableName = GetDeliveryTableName(edgeType.TableName);
            var paramList     = new List <SqlParameter> {
                new SqlParameter("@typeId", edgeType.TypeID)
            };
            var cmdStr = String.Empty;

            foreach (var parentField in edgeType.Fields.Where(x => x.Field.FieldEdgeType != null))
            {
                foreach (var childType in EdgeObjectConfigLoader.FindEdgeTypeInheritors(parentField.Field.FieldEdgeType, EdgeTypes))
                {
                    var tempParentTableName = String.Format("##TempDelivery_{0}", childType.Name);
                    cmdStr = String.Format("{0}UPDATE {1} SET {3}={2}.GK FROM {2} WHERE {1}.TYPEID=@typeId AND {1}.{4}={2}.TK;\n\n",
                                           cmdStr,
                                           mainTableName,
                                           tempParentTableName,
                                           parentField.ColumnNameGK,
                                           parentField.ColumnNameTK);
                }
            }

            // perform update
            using (var cmd = new SqlCommand {
                Connection = _objectsSqlConnection
            })
            {
                cmd.CommandText = cmdStr;
                cmd.Parameters.AddRange(paramList.ToArray());

                cmd.ExecuteNonQuery();
            }
            Log(String.Format("UpdateObjectDependencies:: dependencies updated for edge type '{0}'", edgeType.Name));
        }
예제 #5
0
        /// <summary>
        /// Per each type combine flat SELECT fields by real names in Metrics
        /// </summary>
        /// <param name="accountId"></param>
        /// <param name="stagingTableName"></param>
        /// <param name="connection"></param>
        /// <param name="pipe">Pipe to send SQL rows reply</param>
        public static void GetObjectsView(int accountId, string stagingTableName, SqlConnection connection, SqlPipe pipe)
        {
            // load configuration
            var edgeTypes  = EdgeObjectConfigLoader.LoadEdgeTypes(accountId, connection);
            var edgeFields = EdgeObjectConfigLoader.LoadEdgeFields(accountId, edgeTypes, connection);

            EdgeObjectConfigLoader.SetEdgeTypeEdgeFieldRelation(accountId, edgeTypes, edgeFields, connection);
            var fieldsMap = LoadStageFields(stagingTableName, edgeFields, edgeTypes.Values.ToList(), connection);

            // prepare result record
            var record = new SqlDataRecord(new[]
            {
                new SqlMetaData("TypeID", SqlDbType.Int),
                new SqlMetaData("Name", SqlDbType.NVarChar, 50),
                new SqlMetaData("FieldList", SqlDbType.NVarChar, 1000),
                new SqlMetaData("Select", SqlDbType.NVarChar, 1000)
            });

            pipe.SendResultsStart(record);

            foreach (var type in edgeTypes.Values.Where(x => x.IsAbstract == false))
            {
                // prepare type fields SELECT
                var fieldsStr = String.Empty;
                foreach (var field in type.Fields)
                {
                    fieldsStr = String.Format("{0}{1} AS {2}, ", fieldsStr, field.ColumnNameGK.StartsWith("obj") ? String.Format("COALESCE({0},-1)", field.ColumnNameGK) :
                                              field.ColumnNameGK, field.FieldNameGK);
                    if (field.Field.FieldEdgeType == null)
                    {
                        continue;
                    }

                    // add to select all options of child edge types
                    foreach (var childType in EdgeObjectConfigLoader.FindEdgeTypeInheritors(field.Field.FieldEdgeType, edgeTypes))
                    {
                        if (childType == field.Field.FieldEdgeType)
                        {
                            continue;
                        }
                        fieldsStr = String.Format("{0}{1} AS {2}_{3}_gk, ", fieldsStr, field.ColumnNameGK.StartsWith("obj") ? String.Format("COALESCE({0},-1)", field.ColumnNameGK) :
                                                  field.ColumnNameGK, field.Field.Name, childType.Name);
                    }
                }
                if (fieldsStr.Length <= 0)
                {
                    continue;
                }

                fieldsStr = fieldsStr.Remove(fieldsStr.Length - 2, 2);
                var select = String.Format("SELECT GK,AccountID,RootAccountId,ChannelID,CreatedOn,LastUpdatedOn,{0} FROM {1} WHERE TYPEID={2}", fieldsStr, type.TableName, type.TypeID);

                // set report and and it
                record.SetInt32(0, type.TypeID);
                record.SetString(1, type.Name);
                record.SetString(2, fieldsMap.ContainsKey(type.TypeID) ? String.Join(",", fieldsMap[type.TypeID]) : "");
                record.SetString(3, select);

                pipe.SendResultsRow(record);
            }
            pipe.SendResultsEnd();
        }
예제 #6
0
        /// <summary>
        /// Perfrom metrics staging: insert all metrics table data into staging table
        /// </summary>
        /// <param name="accountId"></param>
        /// <param name="deliveryTableName"></param>
        /// <param name="stagingTableName"></param>
        /// <param name="connection"></param>
        public static string StageMetrics(int accountId, string deliveryTableName, string stagingTableName, SqlConnection connection)
        {
            var selectStr   = String.Empty;
            var insertStr   = String.Empty;
            var fromStr     = String.Format("\t[EdgeDeliveries].{0} AS Metrics\n", deliveryTableName);
            var tablePrefix = deliveryTableName.ToLower().Replace("_metrics]", "").Replace("[dbo].[", "");

            if (!stagingTableName.ToLower().Contains("edgestaging"))
            {
                stagingTableName = String.Format("[EdgeStaging].{0}", stagingTableName);
            }

            var edgeTypes = EdgeObjectConfigLoader.LoadEdgeTypes(accountId, connection);

            // System Fields (e.g. Account, Channel, time, etc.)
            using (var cmd = new SqlCommand("SELECT SystemField FROM [EdgeStaging].[dbo].[SystemFields]", connection))
            {
                using (var reader = cmd.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        selectStr = String.Format("{0}\tMetrics.{1},\n", selectStr, reader["SystemField"]);
                        insertStr = String.Format("{0}\t{1},\n", insertStr, reader["SystemField"]);
                    }
                }
            }

            // metrics fields (according to metrics metadata table)
            var sql = String.Format("SELECT EdgeFieldName, ParentFieldName, EdgeTypeID, MeasureName FROM [EdgeDeliveries].[dbo].[MD_MetricsMetadata] WHERE TABLENAME='{0}'", deliveryTableName);

            using (var cmd = new SqlCommand(sql, connection))
            {
                using (var reader = cmd.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        // add dimension field (JOIN according TK to find GK and WHERE by type ID)
                        if (!String.IsNullOrEmpty(reader["EdgeFieldName"].ToString()))
                        {
                            var edgeType = edgeTypes.Values.FirstOrDefault(x => x.TypeID == int.Parse(reader["EdgeTypeID"].ToString()));
                            if (edgeType == null)
                            {
                                continue;
                            }

                            var fieldName       = reader["EdgeFieldName"].ToString().Replace("_gk", "");
                            var parentFieldName = reader["ParentFieldName"].ToString().Replace("_gk", "");

                            selectStr = String.Format("{0}\tCOALESCE({1}.GK,-1) AS {1}_gk,\n", selectStr, fieldName);
                            insertStr = String.Format("{0}\t{1}_gk,\n", insertStr, fieldName);
                            fromStr   = String.Format("{0}\tLEFT OUTER JOIN {1} AS {3} ON Metrics.{2}_tk={3}.TK\n AND {3}.TYPEID={4}",
                                                      fromStr, GetTableName(tablePrefix, edgeType.TableName), parentFieldName, fieldName, edgeType.TypeID);
                        }
                        // add measure fields
                        else if (!String.IsNullOrEmpty(reader["MeasureName"].ToString()))
                        {
                            selectStr = String.Format("{0}\tMetrics.{1},\n", selectStr, reader["MeasureName"]);
                            insertStr = String.Format("{0}\t{1},\n", insertStr, reader["MeasureName"]);
                        }
                    }
                }
            }

            // perform staging (insert metrics table data into staging table)
            sql = String.Format("INSERT INTO {0} ({1})\nSELECT {2}\nFROM {3}",
                                stagingTableName,
                                insertStr.TrimEnd(new[] { ',', '\n' }),
                                selectStr.TrimEnd(new[] { ',', '\n' }),
                                fromStr);
            using (var cmd = new SqlCommand(sql, connection))
            {
                cmd.ExecuteNonQuery();
            }
            return(sql);
        }