/// <summary> /// Prepare the SQL to load in all values of all fields in the entity request. /// </summary> private void ProcessFields( ) { ISet <IEntityRef> fields = new HashSet <IEntityRef>( ); foreach (var v in _requestNodeMap.Values) { fields.UnionWith(v.Request.Fields); } // Cache whether the fields are virtual BulkRequestHelper.IsVirtualField(fields); // Creates a lookup, that for each type of table contains a list of tuples, // with each tuple matching node tags to fields that need to be loaded for that node tag. ILookup <string, Tuple <int, long> > fieldMap = (from nodeInfo in _requestNodeMap.Values from field in nodeInfo.Request.Fields let fieldInfo = RegisterFieldInfo(field) where !(fieldInfo.IsVirtualAccessControlField || fieldInfo.IsCalculated) select new Tuple <int, long>(nodeInfo.Tag, field.Id) ).ToLookup(MapTagAndFieldPairToTableName); // Create sql foreach (var list in fieldMap) { string tableName = list.Key; // Frustrate injection attack. if (!(tableName.StartsWith("Data_") && tableName.Length < 15)) { throw new InvalidOperationException("Field type table name was invalid: " + tableName); } DataTable dt = TableValuedParameter.Create(TableValuedParameterType.BulkFldType); var map = new HashSet <Tuple <int, long> >( ); foreach (Tuple <int, long> entry in list) { if (map.Contains(entry)) { continue; } map.Add(entry); dt.Rows.Add(entry.Item1, entry.Item2); } string tvpName = "@fld" + tableName; _result.TableValuedParameters [tvpName] = dt; } }
/// <summary> /// Maps field IDs to the database tables that they get stored in. /// </summary> /// <param name="fieldId"></param> /// <returns></returns> private FieldInfo RegisterFieldInfo(IEntityRef fieldId) { // Get/convert the type info for the field (and store for later, since we're already here) FieldInfo fieldInfo; if (!_result.FieldTypes.TryGetValue(fieldId.Id, out fieldInfo)) { // Get the field Field field = Entity.Get <Field>(fieldId.Id); fieldInfo = new FieldInfo(); _result.FieldTypes.Add(fieldId.Id, fieldInfo); fieldInfo.DatabaseType = field.ConvertToDatabaseType(); fieldInfo.IsWriteOnly = field.IsFieldWriteOnly ?? false; fieldInfo.IsCalculated = Factory.CalculatedFieldMetadataProvider.IsCalculatedField(fieldId.Id); fieldInfo.IsVirtualAccessControlField = BulkRequestHelper.IsVirtualAccessControlField(new EntityRef(fieldId)); FieldType fieldType = field.GetFieldType(); fieldInfo.DatabaseTable = string.Intern(fieldType.DbFieldTable); // intern to avoid lots of copies of the same database table names in memory } return(fieldInfo); }