Adding new relationship to the existing array of relationship - hyperledger-composer

I have array of relationship in one of my asset.
asset Patient identified by medicalRecordNumber {
--> LabReports[] labReports optional
}
In a transaction im trying to add new relationship in the array labReports. But its giving me error as TypeError: Cannot read property 'push' of undefined
Here is my logic.js code
var patientId = searchPatient[0].medicalRecordNumber;
var patientRegistry = await getAssetRegistry('org.zcon.healthcare.Patient');
var patientObj = await patientRegistry.get(patientId);
var labreports=[];
labreports=patientObj.labReports;
var newLabReport =factory.newResource('org.zcon.healthcare', 'LabReports', labReportFromattedId);
labreports.push(newLabReport);
patientObj.labReports=labreports;
await patientRegistry.update(patientObj);
How to update the asset ?

Initially you don't have any labReports for patientObj therefore It's undefined and when you try to access push method of undefined property, it throws error.
Try the below solution, It should work
var patientId = searchPatient[0].medicalRecordNumber;
var patientRegistry = await getAssetRegistry('org.zcon.healthcare.Patient');
var patientObj = await patientRegistry.get(patientId);
if(typeof patientObj.labReports !== 'object' || patientObj.labReports.constructor !== Array) {
patientObj.labReports = [];
}
var newLabReport = factory.newResource('org.zcon.healthcare', 'LabReports', labReportFromattedId);
patientObj.labReports.push(newLabReport);
await patientRegistry.update(patientObj);

Related

Why AgilityPack not Loading From Browser dynamic text?

In scraping the following website, I am not get the table in order to scrape. I am waiting for the dynamic text to load. But I never see the results of the correct table.
https://masseyratings.com/nba/games
Here is my Agility Pack code:
var url = "https://masseyratings.com/nba/games";
HtmlWeb web = new HtmlWeb();
var doc = web.LoadFromBrowser(url, o =>
{
var webBrowser = (WebBrowser)o;
// WAIT until the dynamic text is set
return !string.IsNullOrEmpty(webBrowser.Document.GetElementById("mytable0").InnerText);
});
int docLen = doc.Text.Length;
currentSiteData = doc.Text.ToString();
I am not getting any error, I am just not seeing the table of data. And strangely, the HTML tags are getting capitalized.
How can I get the correct data into the currentsiteData variable to further process?
I was able to fix the problem by using the "PuppeteerSharp" and "AngleSharp" nuget package.
Here is my code that works.
using PuppeteerSharp;
using AngleSharp;
var browserFetcher = new BrowserFetcher();
await browserFetcher.DownloadAsync(BrowserFetcher.DefaultChromiumRevision);
var browser = await Puppeteer.LaunchAsync(new LaunchOptions
{
Headless = true
});
var page = await browser.NewPageAsync();
await page.GoToAsync("https://masseyratings.com/nba/games");
var content = await page.GetContentAsync();
var context = BrowsingContext.New(AngleSharp.Configuration.Default);
var document = await context.OpenAsync(req => req.Content(content));
var currentSiteData = document.Source.Text.ToString();

How to update data through Api in Xamarin

I do the update command through the API. Everything seems fine. However, the data is not up to date. When I debug there is no error.
public async Task UpdateViewRatingStore(bool value)
{
var url = baseUrl + userget;
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", mytokenlogin);
string jsonStr = await client.GetStringAsync(url);
var res = JsonConvert.DeserializeObject<Customer>(jsonStr);
var checkunredrating = res.RatingStores;
if (checkunredrating != null)
{
foreach (var r in checkunredrating)
{
r.ID = r.ID;
r.StoreID = r.StoreID;
r.RatingStores = r.RatingStores;
r.CommentStore = r.CommentStore;
r.UserRating = r.UserRating;
r.CreateDay = r.CreateDay;
r.Display = r.Display;
r.ViewStorer = value;
var urlput = baseUrlStoreRating + r.ID;
var stringContent = new StringContent(JsonConvert.SerializeObject(res.RatingStores), Encoding.UTF8, "application/json");
await client.PutAsync(urlput, stringContent);
}
}
}
However when I check in the database it is still not updated. I tested it manually on swagger and Posman was fine. Where did I go wrong? Ask for help. Thank you
you are trying to update a single object, but passing the entire collection every time
instead, try this
foreach (var r in checkunredrating)
{
// you only need to update the changed values
r.ViewStorer = value;
var urlput = baseUrlStoreRating + r.ID;
// only send the current object you are updating
var stringContent = new StringContent(JsonConvert.SerializeObject(r), Encoding.UTF8, "application/json");
await client.PutAsync(urlput, stringContent);
}

In Parse server get() method causes crash

I have a find query with include to get pointer data. It's working fine but if the pointer object does not exist then server crashes.
Here is my query:
var repliesQuery = new Parse.Query("Reply");
repliesQuery.include("author");
repliesQuery.find({
useMasterKey: true
}).then(function(foundMessages) {
var results = [];
for (var i = 0; i < foundMessages.length; i++) {
var rp = {};
rp.title = foundMessages[i].get("title");
rp.description = foundMessages[i].get("description");
var author = foundMessages[i].get("author");
rp.authorId = author.id;
results.push(rp);
}
promise.resolve(results);
});
Everything works fine when the author exists, but if it does not exist then the server crashes.
I tried to add this:
if (author.hasOwnProperty('id')) {
rp.authorId = author.id;
}
But still the issue is not resolved.
Is there any way we can fix this issue?
It's most likely because you're accessing a property of an undefined object, in this case author, in line
rp.authorId = author.id
Like Davi suggests, include a check if author exists.
var repliesQuery = new Parse.Query("Reply");
repliesQuery.include("author");
repliesQuery.find({
useMasterKey: true
}).then(function(foundMessages) {
var results = [];
for (var i = 0; i < foundMessages.length; i++) {
var rp = {};
rp.title = foundMessages[i].get("title");
rp.description = foundMessages[i].get("description");
var author = foundMessages[i].get("author");
if (author) {
rp.authorId = author.id;
}
results.push(rp);
}
promise.resolve(results);
});
Your check
if (author.hasOwnProperty('id')) {
rp.authorId = author.id;
}
also accesses a property of author, so again it would throw an error if author is undefined.

Creating an asynchronous method that contains a linq query

I have a .Net Core 2.2 web app that uses Entity Framework.
In the project, I have this controller that uses Linq to join two tables, and then uses Select to create a node model, like this:
[HttpGet("GameDownloadLinks/{libraryId}")]
public async Task<ActionResult<IEnumerable<GameDownloadLinks>>> GetGameLinksForlibraryAsync(Guid libraryID)
{
var libraryGameLinks = (from gk in _context.GameLinks
join gl in _context.GameList on gk.GameId equals gl.GameId
where gl.libraryId == libraryId
select new GameDownloadLinks
{
LibraryId = gl.libraryId,
LinkText = gk.LinkText,
Price = gk.Price,
GameId = gl.GameId
}).ToList();
var asyncGameDownloadLinks = await Task.WhenAll(libraryGameLinks).toListAsync();
return asyncGameDownloadLinks;
}
I'm trying to make this method asynchronous, but I get this error:
cannot convert from 'System.Collections.Generic.List<Models.GameDownloadLinks>' to 'System.Collections.Generic.IEnumerable<System.Threading.Tasks.Task>'
Some of the answers I found for similar questions indicated this is most likely due to a missing async keyword in the method declaration, but I have included that in mine.
Is there anyway to make this work?
Thanks!
try this
[HttpGet("GameDownloadLinks/{libraryId}")]
public async Task<ActionResult<IEnumerable<GameDownloadLinks>>> GetGameLinksForlibraryAsync(Guid libraryID)
{
var libraryGameLinks = await (from gk in _context.GameLinks
join gl in _context.GameList on gk.GameId equals gl.GameId
where gl.libraryId == libraryId
select new GameDownloadLinks
{
LibraryId = gl.libraryId,
LinkText = gk.LinkText,
Price = gk.Price,
GameId = gl.GameId
}).ToListAsync();
// var asyncGameDownloadLinks = await Task.WhenAll(libraryGameLinks).toListAsync();
return libraryGameLinks ;
}

Running async function in parallel using LINQ's AsParallel()

I have a Document DB repository class that has one get method like below:
private static DocumentClient client;
public async Task<TEntity> Get(string id, string partitionKey = null)
{
try
{
RequestOptions requestOptions = null;
if (partitionKey != null)
{
requestOptions = new RequestOptions { PartitionKey = new PartitionKey(partitionKey) };
}
var result = await client.ReadDocumentAsync(
UriFactory.CreateDocumentUri(DatabaseId, CollectionId, id),
requestOptions);
return (TEntity)(dynamic)result.Resource;
}
catch (DocumentClientException e)
{
// Have logic for different exceptions actually
throw;
}
}
I have two collections - Collection1 and Collection2. Collection1 is non-partitioned whereas Collection2 is partitioned.
On the client side, I create two repository objects, one for each collection.
private static DocumentDBRepository<Collection1Item> collection1Repository = new DocumentDBRepository<Collection1Item>("Collection1");
private static DocumentDBRepository<Collection2Item> collection2Repository = new DocumentDBRepository<Collection2Item>("Collection2");
List<Collection1Item> collection1Items = await collection1Repository.GetItemsFromCollection1(); // Selects first forty documents based on time
List<UIItem> uiItems = new List<UIItem>();
foreach (var item in collection1Items)
{
var collection2Item = await storageRepository.Get(item.Collection2Reference, item.TargetId); // TargetId is my partition key for Collection2
uiItems.Add(new UIItem
{
ItemId = item.ItemId,
Collection1Reference = item.Id,
TargetId = item.TargetId,
Collection2Reference = item.Collection2Reference,
Value = collection2Item.Value
});
}
This works fine. But since it is happening sequentially with foreach, I wanted to do those Get calls in parallel. When I do it in parallel as below:
ConcurrentBag<UIItem> uiItems = new ConcurrentBag<UIItem>();
collection1Items.AsParallel().ForAll(async item => {
var collection2Item = await storageRepository.Get(item.Collection2Reference, item.TargetId); // TargetId is my partition key for Collection2
uiItems.Add(new UIItem
{
ItemId = item.ItemId,
Collection1Reference = item.Id,
TargetId = item.TargetId,
Collection2Reference = item.Collection2Reference,
Value = collection2Item.Value
});
}
);
It doesn't work and uiItems is always empty.
You don't need Parallel.For to run async operations concurrently. If they are truly asynchronous they already run concurrently.
You could collect the task returned from each operation and simply call await Task.WhenAll() on all the tasks. If you modify your lambda to create and return a UIItem, the result of await Task.WhenAll() will be a collection of UIItems. No need to modify global state from inside the concurrent operations.
For example:
var itemTasks = collection1Items.Select(async item =>
{
var collection2Item = await storageRepository.Get(item.Collection2Reference, item.TargetId);
return new UIItem
{
ItemId = item.ItemId,
Collection1Reference = item.Id,
TargetId = item.TargetId,
Collection2Reference = item.Collection2Reference,
Value = collection2Item.Value
}
});
var results= await Task.WhenAll(itemTasks);
A word of caution though - this will fire all Get operations concurrently. That may not be what you want, especially when calling a service with rate limiting.
Try simply starting tasks and waiting for all of them at the end. That would result in parallel execution.
var tasks = collection1Items.Select(async item =>
{
//var collection2Item = await storageRepository.Get...
return new UIItem
{
//...
};
});
var uiItems = await Task.WhenAll(tasks);
PLINQ is useful when working with in-memory constructs and using as many threads as possible, but if used with the async-await technique (which is for releasing threads while accessing external resources), you can end up with strange results.
I would like to share a solution for an issue i saw in some comments.
If you're scared about thread rate limit, and you want to limit this by yourself, you can do something like this, using SemaphoreSlim.
var nbCores = Environment.ProcessorCount;
var semaphore = new SemaphoreSlim(nbCores, nbCores);
var processTasks = items.Select(async x =>
{
await semaphore.WaitAsync();
try
{
await ProcessAsync();
}
finally
{
semaphore.Release();
}
});
await Task.WhenAll(processTasks);
In this example, i called concurrently my "ProcessAsync" but limited to {processor number} concurrent processes.
Hope that's help someone.
NB : You could set the "nbCores" variable as a proper value that satisfy your code condition, of course.
NB 2 : This example is for some use cases, not all of them. I would highly suggest with a big load of task to refer to TPL programming

Resources