private async Task <PersonDetailCollectionResult> GetDetailByArgsOnImplementationAsync(PersonArgs args, PagingArgs paging) { var pdcr = new PersonDetailCollectionResult(new PagingResult(paging)); await _db.StoredProcedure("[Demo].[spPersonGetDetailByArgs]") .Params(p => { p.ParamWithWildcard(args?.FirstName, DbMapper.Default[nameof(Person.FirstName)]) .ParamWithWildcard(args?.LastName, DbMapper.Default[nameof(Person.LastName)]) .TableValuedParamWith(args?.Genders, "GenderIds", () => TableValuedParameter.Create(args.Genders.ToGuidIdList())); }) .SelectQueryMultiSetAsync(pdcr.Paging, new MultiSetCollArgs <PersonCollection, Person>(PersonData.DbMapper.Default, (r) => r.ForEach((p) => { var pd = new PersonDetail(); pd.CopyFrom(p); pdcr.Result.Add(pd); })), new MultiSetCollArgs <WorkHistoryCollection, WorkHistory>(WorkHistoryData.DbMapper.Default, (r) => { PersonDetail pd = null; foreach (var wh in r) { if (pd == null || wh.PersonId != pd.Id) { pd = pdcr.Result.Where(x => x.Id == wh.PersonId).Single(); pd.History = new WorkHistoryCollection(); } pd.History.Add(wh); } })); return(pdcr); }
/// <summary> /// Adds the shallow clone. /// </summary> /// <param name="sourceId">The source identifier.</param> /// <param name="destinationId">The destination identifier.</param> public void AddShallowClone(long sourceId, long destinationId) { DataTable dt; if (!EntityClones.TryGetValue(CloneOption.Shallow, out dt)) { dt = TableValuedParameter.Create(TableValuedParameterType.EntityMap); EntityClones[CloneOption.Shallow] = dt; } dt.Rows.Add(sourceId, destinationId); }
/// <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> /// Populate the input entities datatable. /// </summary> private void PopulateInputEntitiesTable() { if (Entities == null || Entities.Count == 0) { return; } _inputEntitiesTable = TableValuedParameter.Create(TableValuedParameterType.InputEntityType); foreach (IEntity entity in Entities.Values) { if (entity.IsReadOnly) { Mapping[entity.Id] = entity.Id; continue; } var entityInternal = entity as IEntityInternal; if (entityInternal == null) { continue; } if (entityInternal.IsTemporaryId) { bool foundType = false; int isClone = entityInternal.CloneSource == null ? 0 : 1; foreach (long typeId in entity.TypeIds) { _inputEntitiesTable.Rows.Add(entity.Id, typeId, isClone); foundType = true; } if (!foundType) { _inputEntitiesTable.Rows.Add(entity.Id, -1L, isClone); } } else { Mapping[entity.Id] = entity.Id; } } }
public HttpResponseMessage <IDictionary <long, Guid> > GetUpgradeIdsByEntityIds([FromBody] List <long> entityIds) { if (entityIds == null) { throw new WebArgumentNullException("entityIds"); } IDictionary <long, Guid> dict = new Dictionary <long, Guid>(); DataTable dt = TableValuedParameter.Create(TableValuedParameterType.BigInt); foreach (var entityId in entityIds) { dt.Rows.Add(entityId); } using (DatabaseContext context = DatabaseContext.GetContext(false)) { if (context == null) { throw new ArgumentNullException("context"); } using (IDbCommand command = context.CreateCommand()) { command.CommandText = "dbo.spGetUpgradeIdsByEntityIds"; command.CommandType = CommandType.StoredProcedure; command.AddParameter("@tenantId", DbType.Int64, EDC.ReadiNow.IO.RequestContext.TenantId); command.AddTableValuedParameter("@data", dt); using (IDataReader reader = command.ExecuteReader()) { while (reader.Read()) { var id = reader.GetInt64(0); var guid = reader.GetGuid(1); dict[id] = guid; } } } } return(new HttpResponseMessage <IDictionary <long, Guid> >(dict, HttpStatusCode.OK)); }
private void GetByArgsOnQuery(DatabaseParameters p, PersonArgs args, IDatabaseArgs dbArgs) { p.ParamWithWildcard(args?.FirstName, DbMapper.Default[nameof(Person.FirstName)]) .ParamWithWildcard(args?.LastName, DbMapper.Default[nameof(Person.LastName)]) .TableValuedParamWith(args?.Genders, "GenderIds", () => TableValuedParameter.Create(args.Genders.ToGuidIdList())); }
/// <summary> /// Gets the entities that should not be removed as part of an upgrade operation. /// </summary> /// <param name="context">The context.</param> /// <returns></returns> public IEnumerable <Guid> GetDoNotRemove(IProcessingContext context) { // Namely, get the entities that: // 1. used to be part of the application, // 2. which are no longer part of the application, // 3. which are still present in the tenant (i.e. the app developer removed them from the app, but didn't delete them altogether). // 4. we also need to carry over any entities marked as 'do not remove' in previous versions // Step 0: Determine what the original version of this package was Guid?packageId = OriginalPackageId; if (packageId == null) { context.WriteInfo("Tenant application does not have a package Id"); return(Enumerable.Empty <Guid>( )); } // Step 1: Get entities in the previous version LibraryAppSource appLibrarySource = new LibraryAppSource { AppVerId = packageId.Value }; IEnumerable <Guid> entitiesInPrevVersion = appLibrarySource .GetEntities(context) .Select(e => e.EntityId) .ToList( ); // Step 2: Disregard entities that are still in the application IEnumerable <Guid> entitiesInTenantApp = ((IDataSource)this) .GetEntities(context) .Select(e => e.EntityId); IEnumerable <Guid> missingEntities = entitiesInPrevVersion.Except(entitiesInTenantApp).ToList(); // Step 3: Check database to see if the entities are still present ISet <Guid> doNotRemove = new HashSet <Guid>( ); DataTable dt = TableValuedParameter.Create(TableValuedParameterType.Guid); foreach (var guid in missingEntities) { dt.Rows.Add(guid); } using (IDbCommand command = CreateCommand( )) { command.CommandText = "dbo.spGetEntityIdsByUpgradeIds"; command.CommandType = CommandType.StoredProcedure; command.AddParameter("@tenantId", DbType.Int64, TenantId); command.AddTableValuedParameter("@data", dt); using (IDataReader reader = command.ExecuteReader( )) { while (reader.Read( )) { var guid = reader.GetGuid(0); doNotRemove.Add(guid); // entities still in the tenant should be marked as 'do not remove' } } } // Step 4: Include entities marked as 'do not remove' in previous tenants var carriedOver = appLibrarySource.GetDoNotRemove(context); foreach (Guid guid in carriedOver) { doNotRemove.Add(guid); } // Entities that have been removed from the application, but still present in the tenant, // should get marked as 'do not delete' to indicate that when the application is upgraded it should not delete the entities. return(doNotRemove); }
/// <summary> /// Gets the deletions. /// </summary> /// <param name="tableName">Name of the table.</param> /// <param name="tvpType">Type of the TVP.</param> /// <returns></returns> public DataTable GetDeletions(string tableName, TableValuedParameterType tvpType) { return(Get(tableName, Deletions, name => TableValuedParameter.Create(tvpType))); }
private void GetByArgsOnQuery(DatabaseParameters p, PersonArgs args, IDatabaseArgs dbArgs) { p.ParamWithWildcard(args?.FirstName, DbMapper.Default[Person.Property_FirstName]) .ParamWithWildcard(args?.LastName, DbMapper.Default[Person.Property_LastName]) .TableValuedParamWith(args?.Genders, "GenderCodes", () => TableValuedParameter.Create(args.Genders.ToCodeList())); }
/// <summary> /// Prepare the SQL to load in relationships of all applicable types, in one direction. /// </summary> private void ProcessRelationships(Direction relDirection) { // Creates a list of relationship transition rules, where each tuple contains (in order): // 1. the node that the relationship instruction applies to // 2. the relationship ID // 3. the node that the relationship points to var relRequests = from nodeInfo in _requestNodeMap.Values from relReq in nodeInfo.Request.Relationships where Entity.GetDirection(relReq.RelationshipTypeId, relReq.IsReverse) == relDirection select new { NodeInfo = nodeInfo, RelRequest = relReq }; var dt = TableValuedParameter.Create(TableValuedParameterType.BulkRelType); //var relMap = new List<Tuple<int, long, int>>( ); var map = new HashSet <Tuple <int, long, int> >( ); foreach (var relReqInfo in relRequests) { if (relReqInfo.RelRequest.MetadataOnly) { continue; // Don't load actual data } int nodeId = relReqInfo.NodeInfo.Tag; var relReq = relReqInfo.RelRequest; var mapRule = new Tuple <int, long, int>(nodeId, relReq.RelationshipTypeId.Id, _requestNodeMap [relReq.RequestedMembers].Tag); if (!map.Contains(mapRule)) { map.Add(mapRule); dt.Rows.Add(mapRule.Item1, mapRule.Item2, mapRule.Item3); } if (relReq.IsRecursive) { var recursiveRule = new Tuple <int, long, int>(nodeId, relReq.RelationshipTypeId.Id, nodeId); if (!map.Contains(recursiveRule)) { map.Add(recursiveRule); dt.Rows.Add(recursiveRule.Item1, recursiveRule.Item2, recursiveRule.Item3); } } } if (map.Count == 0) { return; } string tblName = relDirection == Direction.Forward ? "@relFwd" : "@relRev"; _result.TableValuedParameters [tblName] = dt; // Gather metadata for relationship requests var relReqs = from node in _request.WalkNodes( ) from relReq in node.Relationships select relReq; foreach (var relReq in relReqs) { var relTypeId = relReq.RelationshipTypeId.Id; var relEntity = Entity.Get <Relationship>(relTypeId); if (relEntity == null) { continue; } long key = relTypeId; var direction = Entity.GetDirection(relReq.RelationshipTypeId, relReq.IsReverse); if (direction == Direction.Reverse) { key = -key; } _result.Relationships [key] = new RelationshipInfo { CloneAction = relEntity.CloneAction_Enum ?? CloneActionEnum_Enumeration.Drop, ReverseCloneAction = relEntity.ReverseCloneAction_Enum ?? CloneActionEnum_Enumeration.Drop, IsLookup = relEntity.IsLookup(direction), ImpliesSecurity = (direction == Direction.Forward ? relEntity.SecuresTo : relEntity.SecuresFrom) ?? false || (relReq.RelationshipTypeId.Alias == "isOfType" && relReq.RelationshipTypeId.Namespace == "core" && !relReq.IsReverse) // Allow types to be loaded implicitly, without granting write to the type. }; } }