/// <summary> /// Stores a list of OBA client stops in Azure Tables /// </summary> /// <param name="stops">list of stops</param> /// <param name="regionId">uniquely identifies the region that these stops belong to</param> /// <returns>task that stores the entities</returns> public async Task Insert(IEnumerable <OBAClient.Model.Stop> stops, string regionId) { // convert the input stops into stop entities List <StopEntity> stopEntities = new List <StopEntity>(); foreach (OBAClient.Model.Stop stop in stops) { StopEntity stopEntity = new StopEntity { Id = stop.Id, Lat = stop.Lat, Lon = stop.Lon, Direction = stop.Direction, Name = stop.Name, Code = stop.Code, RegionId = regionId, RecordType = RecordType.Stop.ToString(), RowState = DataRowState.Default.ToString(), RawContent = stop.RawContent, }; stopEntities.Add(stopEntity); } await this.Insert(stopEntities); }
public StopEntity UpdateStop(JObject entity, int id, int duration) { StopEntity existingStop = GetById(id); JToken value; if (entity.TryGetValue("name", StringComparison.OrdinalIgnoreCase, out value) && (value.Type == JTokenType.String)) { existingStop.Name = value.Value <string>(); } if (entity.TryGetValue("departureTime", StringComparison.OrdinalIgnoreCase, out value) && (value.Type == JTokenType.Date)) { existingStop.DepartureTime = value.Value <DateTime>(); } if (entity.TryGetValue("arrivalTime", StringComparison.OrdinalIgnoreCase, out value) && (value.Type == JTokenType.Date)) { existingStop.ArrivalTime = value.Value <DateTime>(); } if (entity.TryGetValue("cityId", StringComparison.OrdinalIgnoreCase, out value) && (value.Type == JTokenType.Integer)) { existingStop.CityId = value.Value <int>(); } existingStop.Duration = duration; _context.Stops.Update(existingStop); _context.SaveChanges(); return(existingStop); }
/// <summary> /// Get a particular stop from table storage /// </summary> /// <param name="regionId">region Id</param> /// <param name="id">stop Id</param> /// <returns>stop entity</returns> public StopEntity Get(string regionId, string id) { StopEntity partialStop = new StopEntity { Id = id, RegionId = regionId, RecordType = Enum.GetName(typeof(RecordType), RecordType.Stop) }; var retrievedStops = (from entry in this.Table.CreateQuery <DynamicTableEntity>() where entry.PartitionKey == partialStop.PartitionKey && entry.RowKey == partialStop.RowKey && entry.Properties["RecordType"].StringValue == RecordType.Stop.ToString() select entry).Resolve(AbstractEntityAdapter.AdapterResolver <StopEntity>).ToList(); // return null if no records were retrieved if (retrievedStops == null || retrievedStops.Count == 0) { return(null); } // throw an exception if more than 1 record was received if (retrievedStops.Count > 1) { throw new Exception("Expected 1 record but retrieved " + retrievedStops.Count + " records."); } return(retrievedStops[0]); }
public Stop MapToClass(StopEntity stopEntity) { return(new Stop(stopEntity.Latitude, stopEntity.Longitude) { Id = stopEntity.WayPointIndex }); }
/// <summary> /// Delete a published stop from Embedded Social. /// The way we delete a stop is to simply indicate it as deleted /// in the Embedded Social topic title. That way, existing /// comments live on, and users who visit the topic will know /// that this stop is no longer valid. /// </summary> /// <param name="stop">stop that no longer exists</param> /// <returns>task that deletes the stop</returns> public async Task DeleteStop(StopEntity stop) { // check the input this.CheckInputEntity(stop); // update the topic title to indicate this has been deleted await this.UpdateTopic(this.TopicName(stop), DeletedTopicTitlePrefix + this.TopicTitle(stop), this.TopicText(stop), stop.RegionId); }
/// <summary> /// Publish an updated stop to Embedded Social /// </summary> /// <param name="stop">updated stop information</param> /// <returns>task that updates the stop</returns> public async Task UpdateStop(StopEntity stop) { // check the input this.CheckInputEntity(stop); // update the topic await this.UpdateTopic(this.TopicName(stop), this.TopicTitle(stop), this.TopicText(stop), stop.RegionId); }
/// <summary> /// Constructs the topic name for a stop /// </summary> /// <param name="stop">stop information</param> /// <returns>topic name</returns> private string TopicName(StopEntity stop) { string name = "stop_" + stop.RegionId + "_" + stop.Id; // Embedded Social's named topics can store only strings that are safe as an Azure Table key. name = name.StringToTableKey(); return(name); }
private WayPointDto MapToDto(StopEntity stopEntity) { return(new WayPointDto { Id = stopEntity.WayPointIndex, Latitude = stopEntity.Latitude, Longtude = stopEntity.Longitude, }); }
/// <summary> /// Updates a stop in Azure Tables /// </summary> /// <param name="stop">stop</param> /// <returns>task that updates the entity</returns> public async Task Update(StopEntity stop) { // note: this is dangerous because StopEntity is actually not a table entity. // hence it does not contain an Etag that would be used for concurrency control. ITableEntity entity = new EntityAdapter <StopEntity>(stop); entity.ETag = "*"; TableOperation replace = TableOperation.Replace(entity); await this.Table.ExecuteAsync(replace); }
/// <summary> /// Publish a new stop to Embedded Social /// </summary> /// <param name="stop">new stop information</param> /// <returns>task that publishes a new stop and returns the topic name</returns> public async Task <string> CreateStop(StopEntity stop) { // check the input this.CheckInputEntity(stop); // publish the new topic string topicName = this.TopicName(stop); await this.CreateTopic(topicName, this.TopicTitle(stop), this.TopicText(stop), stop.RegionId); // return the topic name return(topicName); }
public Stop UpdateStop(JObject item, int id, int duration) { StopEntity stopEntity = _stopRepository.UpdateStop(item, id, duration); if (stopEntity != null) { return(_stopRepository.GetById(id).ToDomain()); } else { return(null); } }
public int Insert(StopEntity entity) { using var transaction = _context.Database.BeginTransaction(); try { _context.Stops.Add(entity); _context.SaveChanges(); transaction.Commit(); return(entity.StopId); } catch (Exception e) { transaction.Rollback(); return(-1); } }
/// <summary> /// Creates a stop entity with a random Id and name /// </summary> /// <param name="regionId">optional region Id; if not specified, one will be created</param> /// <returns>stop entity</returns> public static StopEntity FakeStopEntity(string regionId = null) { StopEntity stop = new StopEntity() { Id = Guid.NewGuid().ToString(), Lat = 0, Lon = 0, Direction = Guid.NewGuid().ToString(), Name = Guid.NewGuid().ToString(), Code = Guid.NewGuid().ToString(), RegionId = regionId == null?Guid.NewGuid().ToString() : regionId, RecordType = RecordType.Stop.ToString(), RowState = DataRowState.Default.ToString(), RawContent = string.Empty }; return(stop); }
/// <summary> /// Constructs the topic text for a stop /// </summary> /// <param name="stop">stop information</param> /// <returns>topic text</returns> private string TopicText(StopEntity stop) { // in the common case, the topic text will be: // Discuss the stop at Name (Direction) string text = string.Empty; if (!string.IsNullOrWhiteSpace(stop.Name)) { text += "Discuss the stop at " + stop.Name; } if (!string.IsNullOrWhiteSpace(text) && !string.IsNullOrWhiteSpace(stop.Direction)) { text += " (" + stop.Direction + ")"; } return(TopicUtils.RemoveHashtags(text)); }
/// <summary> /// Constructs the topic title for a stop /// </summary> /// <param name="stop">stop information</param> /// <returns>topic title</returns> private string TopicTitle(StopEntity stop) { // in the common case, the topic title will be: // Name (Direction) string title = string.Empty; if (!string.IsNullOrWhiteSpace(stop.Name)) { title += stop.Name; } if (!string.IsNullOrWhiteSpace(title) && !string.IsNullOrWhiteSpace(stop.Direction)) { title += " (" + stop.Direction + ")"; } return(TopicUtils.RemoveHashtags(title)); }
public static Stop ToDomain(this StopEntity stop) { if (stop != null) { return(new Stop { StopId = stop.StopId, CityId = stop.CityId, Name = stop.Name, Duration = stop.Duration, ArrivalTime = stop.ArrivalTime, DepartureTime = stop.DepartureTime }); } else { return(null); } }
/// <summary> /// Checks a stop for validity before publishing to Embedded Social. /// Will throw an exception if invalid. /// </summary> /// <param name="stop">stop</param> private void CheckInputEntity(StopEntity stop) { if (stop == null) { throw new ArgumentNullException("stop"); } else if (string.IsNullOrWhiteSpace(stop.Id)) { throw new ArgumentException("stop id is null or whitespace", "stop"); } else if (string.IsNullOrWhiteSpace(stop.RegionId)) { throw new ArgumentException("stop region id is null or whitespace", "stop"); } else if (string.IsNullOrWhiteSpace(stop.Name)) { throw new ArgumentException("stop name is null or whitespace", "stop"); } }
public void Delete(int id) { using var transaction = _context.Database.BeginTransaction(); try { RouteStopEntity routeStop = _context.RoutesStops.FirstOrDefault(item => item.StopId == id); if (routeStop != null) { _context.RoutesStops.Remove(routeStop); } StopEntity route = _context.Stops.FirstOrDefault(item => item.StopId == id); _context.Stops.Remove(route); _context.SaveChanges(); transaction.Commit(); } catch (Exception e) { transaction.Rollback(); } }
public TourEntity MapToEntity(Tour tour) { var entity = new TourEntity { Id = tour.Id, Stops = new List <StopEntity>() }; for (int i = 0; i < tour.TourStops.Count; i++) { Stop stop = tour.TourStops[i]; var stopEntity = new StopEntity { Latitude = stop.Latitude, Longitude = stop.Longitude, Tour = entity, WayPointIndex = i }; entity.Stops.Add(stopEntity); } return(entity); }
/// <summary> /// Resurrect a published stop from Embedded Social. /// The way we delete a stop is to simply indicate it as deleted /// in the Embedded Social topic title. To resurrect it, that /// text has to be removed from the topic title. /// </summary> /// <param name="stop">stop that has been restored</param> /// <returns>task that deletes the stop</returns> public async Task ResurrectStop(StopEntity stop) { await this.UpdateStop(stop); }
/// <summary> /// Stores a stop in Azure Tables /// </summary> /// <param name="stop">stop</param> /// <returns>task that stores the entity</returns> public async Task Insert(StopEntity stop) { await this.Insert(new List <StopEntity>() { stop }); }
public async Task ResurrectEntities() { // this test messes with the publish table so it should not be run on production accounts Assert.IsFalse(Utils.ProdConfiguration.IsProduction(TestConstants.AzureStorageConnectionString)); string runId = RunId.GenerateTestRunId(); // clean the publish table so that we are working with known state StorageManager publishStorage = new StorageManager(TestConstants.AzureStorageConnectionString, TableNames.TableType.Publish, runId); await TestUtilities.CleanPublishStorage(publishStorage); // setup download storage StorageManager downloadStorage = new StorageManager(TestConstants.AzureStorageConnectionString, TableNames.TableType.Download, runId); await downloadStorage.CreateTables(); // create region RegionEntity region = TestUtilities.FakeRegionEntity(); await downloadStorage.RegionStore.Insert(new List <RegionEntity>() { region }); // create agency AgencyEntity agency = TestUtilities.FakeAgencyEntity(region.Id); await downloadStorage.AgencyStore.Insert(new List <AgencyEntity>() { agency }); // create 1 route and 1 stop in download table that also exist in the publish table as deleted entities RouteEntity existingRoute = TestUtilities.FakeRouteEntity(region.Id, agency.Id); await downloadStorage.RouteStore.Insert(existingRoute); existingRoute.RowState = DataRowState.Delete.ToString(); await publishStorage.RouteStore.Insert(existingRoute); StopEntity existingStop = TestUtilities.FakeStopEntity(region.Id); await downloadStorage.StopStore.Insert(existingStop); existingStop.RowState = DataRowState.Delete.ToString(); await publishStorage.StopStore.Insert(existingStop); // setup diff manager DiffManager diffManager = new DiffManager(TestConstants.AzureStorageConnectionString, runId); await diffManager.InitializeStorage(); // execute diff manager await diffManager.DiffAndStore(); // sleep between the insert and the query otherwise Azure sometimes returns no records Thread.Sleep(TestConstants.AzureTableDelay); // query results StorageManager diffStorage = new StorageManager(TestConstants.AzureStorageConnectionString, TableNames.TableType.Diff, runId); IEnumerable <RouteEntity> diffRoutes = await diffStorage.RouteStore.GetAllRoutes(existingRoute.RegionId); IEnumerable <StopEntity> diffStops = await diffStorage.StopStore.GetAllStops(existingStop.RegionId); StorageManager diffMetadataStorage = new StorageManager(TestConstants.AzureStorageConnectionString, TableNames.TableType.DiffMetadata, runId); List <DiffMetadataEntity> diffMetadata = diffMetadataStorage.DiffMetadataStore.Get(runId).ToList(); // clean up await diffManager.DeleteDiff(); await downloadStorage.DeleteDataTables(); await publishStorage.DeleteTables(); // check route Assert.IsNotNull(diffRoutes); Assert.AreEqual(diffRoutes.Count(), 1); Assert.AreEqual(diffRoutes.First().Id, existingRoute.Id); Assert.AreEqual(diffRoutes.First().ShortName, existingRoute.ShortName); Assert.AreEqual(diffRoutes.First().LongName, existingRoute.LongName); Assert.AreEqual(diffRoutes.First().Description, existingRoute.Description); Assert.AreEqual(diffRoutes.First().Url, existingRoute.Url); Assert.AreEqual(diffRoutes.First().AgencyId, existingRoute.AgencyId); Assert.AreEqual(diffRoutes.First().RegionId, existingRoute.RegionId); Assert.AreEqual(diffRoutes.First().RecordType, existingRoute.RecordType); Assert.AreEqual(diffRoutes.First().RowState, DataRowState.Resurrect.ToString()); Assert.AreEqual(diffRoutes.First().RawContent, existingRoute.RawContent); // check stop Assert.IsNotNull(diffStops); Assert.AreEqual(diffStops.Count(), 1); Assert.AreEqual(diffStops.First().Id, existingStop.Id); Assert.AreEqual(diffStops.First().Lat, existingStop.Lat); Assert.AreEqual(diffStops.First().Lon, existingStop.Lon); Assert.AreEqual(diffStops.First().Direction, existingStop.Direction); Assert.AreEqual(diffStops.First().Name, existingStop.Name); Assert.AreEqual(diffStops.First().Code, existingStop.Code); Assert.AreEqual(diffStops.First().RegionId, existingStop.RegionId); Assert.AreEqual(diffStops.First().RecordType, existingStop.RecordType); Assert.AreEqual(diffStops.First().RowState, DataRowState.Resurrect.ToString()); Assert.AreEqual(diffStops.First().RawContent, existingStop.RawContent); // check metadata Assert.IsNotNull(diffMetadata); Assert.AreEqual(diffMetadata.Count, 2); int routeIndex = -1; int stopIndex = -1; if (diffMetadata[0].RecordType == RecordType.Route.ToString()) { routeIndex = 0; stopIndex = 1; } else { routeIndex = 1; stopIndex = 0; } Assert.AreEqual(diffMetadata[routeIndex].AddedCount, 0); Assert.AreEqual(diffMetadata[routeIndex].AgencyId, existingRoute.AgencyId); Assert.AreEqual(diffMetadata[routeIndex].DeletedCount, 0); Assert.AreEqual(diffMetadata[routeIndex].RecordType, RecordType.Route.ToString()); Assert.AreEqual(diffMetadata[routeIndex].RegionId, existingRoute.RegionId); Assert.AreEqual(diffMetadata[routeIndex].ResurrectedCount, 1); Assert.AreEqual(diffMetadata[routeIndex].RunId, runId); Assert.AreEqual(diffMetadata[routeIndex].UpdatedCount, 0); Assert.AreEqual(diffMetadata[stopIndex].AddedCount, 0); Assert.AreEqual(diffMetadata[stopIndex].AgencyId, string.Empty); Assert.AreEqual(diffMetadata[stopIndex].DeletedCount, 0); Assert.AreEqual(diffMetadata[stopIndex].RecordType, RecordType.Stop.ToString()); Assert.AreEqual(diffMetadata[stopIndex].RegionId, existingStop.RegionId); Assert.AreEqual(diffMetadata[stopIndex].ResurrectedCount, 1); Assert.AreEqual(diffMetadata[stopIndex].RunId, runId); Assert.AreEqual(diffMetadata[stopIndex].UpdatedCount, 0); }