protected IEnumerable <Row> CreateRows(DbSetInfo dbSetInfo, IEnumerable <object> dataSource, int rowCount) { var fields = dbSetInfo.fieldInfos.Where(f => f.isIncludeInResult()).OrderBy(f => f._ordinal).ToArray(); int fieldsCnt = fields.Length; FieldInfo[] pkInfos = dbSetInfo.GetPKFieldInfos(); Row[] rows = new Row[rowCount]; int counter = 0; foreach (object entity in dataSource) { Row row = new Row(); string[] pk = new string[pkInfos.Length]; row.values = new string[fieldsCnt]; for (int i = 0; i < fieldsCnt; ++i) { string fv = null; FieldInfo fld = fields[i]; fv = this.DataHelper.GetFieldValueAsString(entity, fld.fieldName); int keyIndex = Array.IndexOf(pkInfos, fld); if (keyIndex > -1) { pk[keyIndex] = fv; } row.values[i] = fv; } row.key = string.Join(";", pk); rows[counter] = row; ++counter; } return(rows); }
protected void UpdateRowInfoAfterUpdates(RowInfo rowInfo) { DbSetInfo dbSetInfo = rowInfo.dbSetInfo; var fields = dbSetInfo.GetFieldByNames(); rowInfo.values.ForEach((fv) => { FieldInfo finfo = fields[fv.fieldName]; if (!finfo.isIncludeInResult()) { return; } string newVal; if (this.isEntityValueChanged(rowInfo, finfo.fieldName, out newVal)) { fv.val = newVal; fv.flags = fv.flags | ValueFlags.Refreshed; } }); if (rowInfo.changeType == ChangeType.Added) { rowInfo.serverKey = rowInfo.GetRowKeyAsString(); } }
public string GetRowKeyAsString(DbSetInfo dbSetInfo) { FieldInfo[] finfos = DataHelper.GetPKFieldInfos(dbSetInfo); string[] vals = new string[finfos.Length]; for (int i = 0; i < finfos.Length; ++i) { ValueChange fv = this.GetValue(finfos[i].fieldName); vals[i] = fv.val; } return(string.Join(";", vals)); }
public object GetTypedValue(Type entityType, DbSetInfo dbSetInfo) { FieldInfo fi = dbSetInfo.GetFieldByNames()[this.fieldName]; PropertyInfo pinfo = entityType.GetProperty(fi.fieldName); if (pinfo == null) { throw new Exception(string.Format(ErrorStrings.ERR_PROPERTY_IS_MISSING, entityType.Name, fi.fieldName)); } Type propType = pinfo.PropertyType; return(DataHelper.ConvertToTyped(propType, fi.dataType, fi.dateConversion, this.val)); }
protected IEnumerable <IncludedResult> CreateIncludedResults(DbSetInfo dbSetInfo, IEnumerable <object> entities, string[] includePaths) { if (includePaths.Length == 0) { return(Enumerable.Empty <IncludedResult>()); } Dictionary <string, IncludedResult> visited = new Dictionary <string, IncludedResult>(); var metadata = this.EnsureMetadataInitialized(); foreach (string includePath in includePaths) { string[] pathParts = includePath.Split('.'); string[] nextParts = pathParts.Skip(1).ToArray(); this.CreateIncludedResult(dbSetInfo, entities, pathParts[0], nextParts, visited); } return(visited.Values); }
protected virtual void AuthorizeChangeSet(ChangeSet changeSet) { try { var metadata = this.EnsureMetadataInitialized(); foreach (var dbSet in changeSet.dbSets) { //methods on domain service which are attempted to be executed by client (SaveChanges triggers their execution) Dictionary <string, MethodInfo> domainServiceMethods = new Dictionary <string, MethodInfo>(); DbSetInfo dbInfo = metadata.dbSets[dbSet.dbSetName]; this._currentDbSet = dbSet; foreach (RowInfo rowInfo in dbSet.rows) { this._currentRowInfo = rowInfo; MethodInfo methInfo = null; try { methInfo = SecurityHelper.GetCRUDMethodInfo(dbInfo, rowInfo); } finally { this._currentRowInfo = null; } if (methInfo == null) { throw new DomainServiceException(string.Format(ErrorStrings.ERR_REC_CHANGETYPE_INVALID, dbInfo.EntityType.Name, rowInfo.changeType)); } if (!domainServiceMethods.ContainsKey(methInfo.Name)) { domainServiceMethods.Add(methInfo.Name, methInfo); } } // foreach (RowInfo rowInfo in dbSet.rows) this.Authorizer.CheckUserRightsToExecute(domainServiceMethods.Values.ToArray()); } //foreach (var dbSet in changeSet.dbSets) } finally { this._currentDbSet = null; } }
public void Prepare() { var rowsMap = this.GetRowsMap(); foreach (var trackAssoc in changeSet.trackAssocs) { var assoc = this._metadata.associations[trackAssoc.assocName]; string pkey = string.Format("{0}:{1}", assoc.parentDbSetName, trackAssoc.parentKey); string ckey = string.Format("{0}:{1}", assoc.childDbSetName, trackAssoc.childKey); RowInfo parent = rowsMap[pkey]; RowInfo child = rowsMap[ckey]; ParentChildNode childNode = new ParentChildNode(child); childNode.association = assoc; childNode.ParentRow = parent; updateNodes.AddLast(childNode); } foreach (var dbSet in this.GetSortedDbSets()) { foreach (RowInfo rowInfo in dbSet.rows) { DbSetInfo dbSetInfo = rowInfo.dbSetInfo; _allList.AddLast(rowInfo); switch (rowInfo.changeType) { case ChangeType.Added: _insertList.AddLast(rowInfo); break; case ChangeType.Deleted: _insertList.AddFirst(rowInfo); break; case ChangeType.Updated: _updateList.AddLast(rowInfo); break; default: throw new DomainServiceException(string.Format(ErrorStrings.ERR_REC_CHANGETYPE_INVALID, dbSetInfo.EntityType.Name, rowInfo.changeType)); } } } }
protected void InsertEntity(RowInfo rowInfo) { DbSetInfo dbSetInfo = rowInfo.dbSetInfo; if (rowInfo.changeType != ChangeType.Added) { throw new DomainServiceException(string.Format(ErrorStrings.ERR_REC_CHANGETYPE_INVALID, dbSetInfo.EntityType.Name, rowInfo.changeType)); } MethodInfo methInfo = this.GetOperMethodInfo(dbSetInfo, OperationNames.CREATE); if (methInfo == null) { throw new DomainServiceException(string.Format(ErrorStrings.ERR_DB_INSERT_NOT_IMPLEMENTED, dbSetInfo.EntityType.Name, this.GetType().Name)); } object dbEntity = Activator.CreateInstance(dbSetInfo.EntityType); UpdateEntityFromRowInfo(dbEntity, rowInfo, false); rowInfo.changeState.Entity = dbEntity; methInfo.Invoke(this, new object[] { dbEntity }); }
private Dictionary <string, RowInfo> GetRowsMap() { Dictionary <string, RowInfo> result = new Dictionary <string, RowInfo>(); foreach (var dbSet in changeSet.dbSets) { DbSetInfo dbSetInfo = this._metadata.dbSets[dbSet.dbSetName]; if (dbSetInfo.EntityType == null) { throw new DomainServiceException(string.Format(ErrorStrings.ERR_DB_ENTITYTYPE_INVALID, dbSetInfo.dbSetName)); } foreach (RowInfo rowInfo in dbSet.rows) { rowInfo.dbSetInfo = dbSetInfo; result.Add(GetKey(rowInfo), rowInfo); } } return(result); }
protected void UpdateRowInfoFromEntity(object entity, RowInfo rowInfo) { DbSetInfo dbSetInfo = rowInfo.dbSetInfo; var values = rowInfo.values; var fields = dbSetInfo.GetFieldByNames(); values.ForEach((fv) => { FieldInfo finfo = fields[fv.fieldName]; if (!finfo.isIncludeInResult()) { return; } fv.val = this.DataHelper.GetFieldValueAsString(entity, finfo.fieldName); fv.flags = fv.flags | ValueFlags.Refreshed; }); if (rowInfo.changeType == ChangeType.Added) { rowInfo.serverKey = rowInfo.GetRowKeyAsString(); } }
protected virtual void ApplyChangesToEntity(RowInfo rowInfo) { DbSetInfo dbSetInfo = rowInfo.dbSetInfo; if (dbSetInfo.EntityType == null) { throw new DomainServiceException(string.Format(ErrorStrings.ERR_DB_ENTITYTYPE_INVALID, dbSetInfo.dbSetName)); } try { switch (rowInfo.changeType) { case ChangeType.Added: this.InsertEntity(rowInfo); break; case ChangeType.Deleted: this.DeleteEntity(rowInfo); break; case ChangeType.Updated: this.UpdateEntity(rowInfo); break; default: throw new DomainServiceException(string.Format(ErrorStrings.ERR_REC_CHANGETYPE_INVALID, dbSetInfo.EntityType.Name, rowInfo.changeType)); } } catch (Exception ex) { object dbEntity = rowInfo.changeState == null ? null : rowInfo.changeState.Entity; rowInfo.changeState = new EntityChangeState { Entity = dbEntity, Error = ex }; this.OnError(ex); throw; } }
protected void UpdateEntity(RowInfo rowInfo) { DbSetInfo dbSetInfo = rowInfo.dbSetInfo; if (rowInfo.changeType != ChangeType.Updated) { throw new DomainServiceException(string.Format(ErrorStrings.ERR_REC_CHANGETYPE_INVALID, dbSetInfo.EntityType.Name, rowInfo.changeType)); } MethodInfo methInfo = this.GetOperMethodInfo(dbSetInfo, OperationNames.UPDATE); if (methInfo == null) { throw new DomainServiceException(string.Format(ErrorStrings.ERR_DB_UPDATE_NOT_IMPLEMENTED, dbSetInfo.EntityType.Name, this.GetType().Name)); } object dbEntity = Activator.CreateInstance(dbSetInfo.EntityType); UpdateEntityFromRowInfo(dbEntity, this._currentRowInfo, false); var original = this.GetOriginal(dbEntity); rowInfo.changeState.Entity = dbEntity; rowInfo.changeState.OriginalEntity = original; //apply this changes to entity that is in the database (this is done in user domain service method) methInfo.Invoke(this, new object[] { dbEntity }); }
protected bool ValidateEntity(RowInfo rowInfo) { DbSetInfo dbSetInfo = rowInfo.dbSetInfo; IEnumerable <ValidationErrorInfo> errs = null; LinkedList <string> mustBeChecked = new LinkedList <string>(); LinkedList <string> skipCheckList = null; if (rowInfo.changeType == ChangeType.Added) { skipCheckList = new LinkedList <string>(); foreach (var pn in rowInfo.changeState.ParentRows) { foreach (var frel in pn.association.fieldRels) { skipCheckList.AddLast(frel.childField); } } } foreach (var fieldInfo in dbSetInfo.fieldInfos) { if (!fieldInfo.isIncludeInResult()) { continue; } string value = this.DataHelper.GetFieldValueAsString(rowInfo.changeState.Entity, fieldInfo.fieldName); if (rowInfo.changeType == ChangeType.Added) { bool isSkip = fieldInfo.isAutoGenerated || (skipCheckList != null && skipCheckList.Any(n => n == fieldInfo.fieldName)); if (!isSkip) { this.ValidationHelper.CheckValue(fieldInfo, value); mustBeChecked.AddLast(fieldInfo.fieldName); } } else if (rowInfo.changeType == ChangeType.Updated) { string newVal; bool isChanged = isEntityValueChanged(rowInfo, fieldInfo.fieldName, out newVal); if (isChanged) { this.ValidationHelper.CheckValue(fieldInfo, newVal); } if (isChanged) { mustBeChecked.AddLast(fieldInfo.fieldName); } } } rowInfo.changeState.NamesOfChangedFields = mustBeChecked.ToArray(); MethodInfo methInfo = this.GetOperMethodInfo(dbSetInfo, OperationNames.VALIDATE); if (methInfo != null) { errs = (IEnumerable <ValidationErrorInfo>)methInfo.Invoke(this, new object[] { rowInfo.changeState.Entity, rowInfo.changeState.NamesOfChangedFields }); } if (errs != null && errs.Count() > 0) { rowInfo.changeState.ValidationErrors = errs.ToArray(); return(false); } return(true); }
protected void UpdateEntityFromRowInfo(object entity, RowInfo rowInfo, bool isOriginal) { DbSetInfo dbSetInfo = rowInfo.dbSetInfo; var values = rowInfo.values; var flds = dbSetInfo.GetFieldByNames(); foreach (ValueChange fv in values) { FieldInfo finfo = flds[fv.fieldName]; if (!finfo.isIncludeInResult()) { continue; } if (isOriginal) { if ((fv.flags & ValueFlags.Setted) == ValueFlags.Setted) { this.DataHelper.SetValue(entity, finfo, fv.orig); } } else { switch (rowInfo.changeType) { case ChangeType.Deleted: { //For delete fill only original values if ((fv.flags & ValueFlags.Setted) == ValueFlags.Setted) { this.DataHelper.SetValue(entity, finfo, fv.orig); } } break; case ChangeType.Added: { if (finfo.isAutoGenerated) { continue; } if ((fv.flags & ValueFlags.Changed) == ValueFlags.Changed) { if (finfo.isReadOnly && fv.val != null && !finfo.allowClientDefault) { throw new DomainServiceException(string.Format(ErrorStrings.ERR_PROPERTY_IS_READONLY, finfo.fieldName)); } if (finfo.isAutoGenerated && fv.val != null) { throw new DomainServiceException(string.Format(ErrorStrings.ERR_PROPERTY_IS_READONLY, finfo.fieldName)); } this.DataHelper.SetValue(entity, finfo, fv.val); } } break; case ChangeType.Updated: { if ((fv.flags & ValueFlags.Changed) == ValueFlags.Changed) { if (finfo.isReadOnly || (finfo.isPrimaryKey > 0 || finfo.isRowTimeStamp || finfo.isAutoGenerated)) { throw new DomainServiceException(string.Format(ErrorStrings.ERR_PROPERTY_IS_READONLY, finfo.fieldName)); } if (!finfo.isNullable && fv.val == null) { throw new DomainServiceException(string.Format(ErrorStrings.ERR_FIELD_IS_NOT_NULLABLE, finfo.fieldName)); } this.DataHelper.SetValue(entity, finfo, fv.val); } else if ((fv.flags & ValueFlags.Setted) == ValueFlags.Setted) { if ((finfo.isPrimaryKey > 0 || finfo.isRowTimeStamp || finfo.isNeedOriginal) && fv.val != fv.orig) { throw new DomainServiceException(string.Format(ErrorStrings.ERR_VAL_ORIGINAL_INVALID, finfo.fieldName)); } this.DataHelper.SetValue(entity, finfo, fv.val); } } break; } } } if (!isOriginal && rowInfo.changeType == ChangeType.Added) { foreach (var pn in rowInfo.changeState.ParentRows) { if (!this.DataHelper.SetProperty(entity, pn.association.childToParentName, pn.ParentRow.changeState.Entity)) { throw new DomainServiceException(string.Format(ErrorStrings.ERR_CAN_NOT_SET_PARENT_FIELD, pn.association.childToParentName, rowInfo.dbSetInfo.EntityType.Name)); } } } }
protected MethodInfo GetOperMethodInfo(DbSetInfo dbSetInfo, string oper) { return(dbSetInfo.getOperationMethodInfo(oper)); }
private void CreateIncludedResult(DbSetInfo dbSetInfo, IEnumerable <object> inputEntities, string propertyName, string[] nextParts, Dictionary <string, IncludedResult> visited) { var metadata = this.EnsureMetadataInitialized(); bool isChildProperty = false; DbSetInfo nextDbSetInfo = null; var assoc = metadata.associations.Values.Where(a => a.parentDbSetName == dbSetInfo.dbSetName && a.parentToChildrenName == propertyName).FirstOrDefault(); if (assoc != null) { isChildProperty = true; nextDbSetInfo = metadata.dbSets[assoc.childDbSetName]; } else { assoc = metadata.associations.Values.Where(a => a.childDbSetName == dbSetInfo.dbSetName && a.childToParentName == propertyName).FirstOrDefault(); if (assoc == null) { throw new DomainServiceException(string.Format(ErrorStrings.ERR_INCL_NAVIG_INVALID, propertyName + (nextParts.Length > 0?("." + string.Join(".", nextParts)):""))); } nextDbSetInfo = metadata.dbSets[assoc.parentDbSetName]; } if (visited.ContainsKey(nextDbSetInfo.dbSetName + "." + propertyName)) { return; } int rowCount = 0; object propValue; LinkedList <object> resultEntities = new LinkedList <object>(); foreach (object entity in inputEntities) { propValue = this.DataHelper.GetProperty(entity, propertyName); if (isChildProperty && propValue is IEnumerable) { foreach (object childEntity in (IEnumerable)propValue) { resultEntities.AddLast(childEntity); ++rowCount; } } else if (!isChildProperty && propValue != null) { resultEntities.AddLast(propValue); ++rowCount; } } //create temporary result without rows //fills rows at the end of the method IncludedResult current = new IncludedResult { dbSetName = nextDbSetInfo.dbSetName, rows = new Row[0], names = nextDbSetInfo.fieldInfos.Where(f => f.isIncludeInResult()).OrderBy(f => f._ordinal).Select(fi => fi.fieldName) }; visited.Add(nextDbSetInfo.dbSetName + "." + propertyName, current); if (nextParts.Length > 0) { this.CreateIncludedResult(nextDbSetInfo, resultEntities, nextParts[0], nextParts.Skip(1).ToArray(), visited); } //map rows by PK Dictionary <string, Row> rows = new Dictionary <string, Row>(rowCount); var fields = nextDbSetInfo.fieldInfos.Where(f => f.isIncludeInResult()).OrderBy(f => f._ordinal).ToArray(); int fieldCnt = fields.Length; FieldInfo[] pkInfos = nextDbSetInfo.GetPKFieldInfos(); int counter = 0; foreach (object entity in resultEntities) { Row row = new Row(); string[] pk = new string[pkInfos.Length]; row.values = new string[fieldCnt]; for (int i = 0; i < fieldCnt; ++i) { string fv = null; FieldInfo fld = fields[i]; fv = this.DataHelper.GetFieldValueAsString(entity, fld.fieldName); int keyIndex = Array.IndexOf(pkInfos, fld); if (keyIndex > -1) { pk[keyIndex] = fv; } row.values[i] = fv; } row.key = string.Join(";", pk); //here we filter out repeated rows if (!rows.ContainsKey(row.key)) { rows.Add(row.key, row); ++counter; } } current.rows = rows.Values; current.rowCount = counter; }