Exception: when trying to use Enumerable.Any Method with Mobile Services query - linq

I have a mobile app build with Xamarin Forms and I'm using Offline Data Sync in Azure Mobile Apps, to enable offline sync in my mobile application
so,
I have two tables
PurchaseOrders
PurcahseOrderDetails
public IMobileServiceSyncTable<PurchaseOrders> PurchaseOrdersTable;
public IMobileServiceSyncTable<PurchaseOrderDetails> PurchaseOrderDetailsTable;
and I want to sync the records in the PurchaseOrders Table based on UserId
and then sync the records in PurchaseOrderDetails Table based on Id of PurcahseOrder
To do that I'm trying this
Get Purchase Orders based on User Id
var purchaseOrders = (await GetAllPurchaseOrdersAsync(syncFromServer:true, userId)).ToList();
// in sync method
await PurchaseOrdersTable.PullAsync(queryName, PurchaseOrdersTable.CreateQuery().Where(w => w.Userid == userId));
When I'm trying to get Purchase Order Details based on Id in the list of PurchaseOrders
await PurchaseOrderDetailsTable.PullAsync(queryName,
PurchaseOrderDetailsTable.CreateQuery().Where(pod => purchaseOrders.Any(po => po.Id == pod.PoId)));
I get the exception below
'value(System.Collections.Generic.List`1[ProjectName.Models.PurchaseOrder]).Any(po => (po.Id == pod.PoId))' is not supported in a 'Where' Mobile Services query expression.
Can I get an explanation about the error above and how to solve it?

If your mobile data is backed by table service, then Any is not a supported LINQ operator (see: https://learn.microsoft.com/en-us/rest/api/storageservices/query-operators-supported-for-the-table-service) so that might be source of the exception.
Since PurchaseOrder doesn't contain a collection of PurchaseOrderDetail, one workaround I can think of is to iterate on purchaseOrders and select from purchaseOrderDetails.
var poDetails = new List<PurchaseOrderDetail>();
foreach (var po in purchaseOrders)
{
var poDetail = await PurchaseOrderDetails.PullAsync(queryName, PurchaseOrderDetailsTable.CreateQuery().Where(pod => po.Id == pod.PoId);
poDetails.Add(poDetail);
}

Related

retrieving id of notification that is inserted using PublishAsync method is not implemented

I am using ASP.NET Boilerplate with Code-First Entity Framework and MVC 5.
and in order to send a notification I am using the following code
public async Task SendNotification(Guid auditId, int auditNo, int? tenantId, long userId)
{
var notificationData = new LocalizableMessageNotificationData(
new LocalizableString(
"NotificationName",
EODAConsts.LocalizationSourceName
)
);
notificationData["auditNo"] = auditNo;
notificationData["auditId"] = auditId;
await _notificationPublisher.PublishAsync(NotificationName, notificationData, severity: NotificationSeverity.Error, userIds: new[] { new UserIdentifier(tenantId, userId) });
}
we know that sending the notification means adding it to AbpTenantNotifications and AbpUserNotifications ,but after sending it what is the way to retrieve inserted notification id in AbpTenantNotifications ,because PublishAsync method doesn't return any value
i mean what is the unique key in table AbpTenantNotifications which insures selecting specific one notification that is inserted after calling PublishAsync method
NotificationInfo only persist in the table for a short time only.
When you calls PublishAsync, NotifcationInfo is created immediately (see here).
Subsequently, it is consumed by NotificationDistributor.DistributeAsync and deleted right after converting NotificationInfo into TenantNotification & UserNotification (see here)
If you want to capture the TenantNotification when it is created, you can try with entity event handler (see here)

LINQ to query Service Fabric Reliable Collections?

Are there any plans in adding LINQ support for Reliable Collections on Service Fabric? Does anyone know of any extensions that can enable this? It seems like this was possible in a previous API version but not anymore.
On a reliable dictionary, you can use CreateEnumerableAsync to create an async enumerable. (Documentation here.)
Next, you can create linq queries by using Eli's extension methods here.
Example from gist:
var accounts = await (await accountNames.CreateLinqAsyncEnumerable(txn))
.Where(x => x.Value.IndexOf(name, StringComparison.InvariantCultureIgnoreCase) >= 0)
.SelectAsync(async x => new Account
{
Id = x.Key,
Name = x.Value,
Data = (await accountData.TryGetValueAsync(txn, x.Key)).Value
})
.ToList();

XrmServiceContext object is not getting the latest data from CRM

i have a wcf which connects to crm (on prem) to retrieve an account record. i can see when the entity is retrieved it does not hold the current record i.e. some field will still hold the old column value. i tried with various merge option with no avail. please see the code below
using (XrmServiceContext cContext = new XrmServiceContext(con))
{
Entity ent = cContext.Retrieve(ConstantKVP.AccountSchema.ENTITY_LOGICAL_NAME, AccountId, new ColumnSet(true));
}
any suggestions?
Is it possible the data is being cached?
cContext.TryAccessCache(cache => cache.Mode = OrganizationServiceCacheMode.Disabled);
I took this approach for a CrmOrganizationServiceContext, so perhaps the same theory applies.
After save use clear changes cContext.ClearChanges();
For retrieves use MergeOption.OverwriteChanges
Or
Create a new XrmServiceContext object by passing a newed up organizationservice:
var uncachedOrganizationService = new OrganizationService("Xrm");
var uncachedXrmServiceContext = new XrmServiceContext(uncachedOrganizationService);
var ent = uncachedXrmServiceContext.Retrieve(ConstantKVP.AccountSchema.ENTITY_LOGICAL_NAME,AccountId,new ColumnSet(true));

botframework handling attachments per user and conversation

In my bot I would like to accept attachments from users.
I know how to receive them in :
public async Task<Message> Post([FromBody]Message message)
{
if (message.Type == "Message")
{
if (message.Attachments.Count > 0)
{
foreach (var afile in message.Attachments)
{
lstFiles.Add(afile.ContentUrl);
}
}
what I am doing here is storing them as they arrive in lstFiles that is list of strings private to class MessagesController : ApiController, this way I know I can have those files and their URLs
When users finishes answering the questions ( I am using FormFlow) in the Do event I store his input in Azure storage table
internal static IDialog<VGMData> MakeRootDialog()
{
return Chain.From(() => FormDialog.FromForm(VEMData.BuildForm))
.Do(async (context, order) =>
{
var completed = await order;
StoreAndSendEmailConfirmations(completed);
await context.PostAsync("And I am done... ..");
}
I can not understand how can I have access to attached files in the .Do function so that I can initiate download and subsequent storage in azure blob for files submitted by user and within his conversation. Only thing I seem to have is 'context' and 'order' that is user data replies but without attachment files.
I can get there lstFiles, but I am afraid it may contain files from different simultaneous users and conversations.
thanks in advance,
Roman
You might want to consider storing the list of attachments in the PerUserPerConversation data bag. In that way you can ensure that you will be retrieving the data related to the user participating in that conversation.
Here is the documentation around how the bot track state.

asp.net web api 2 identity performance

Can we tune the performance of default asp.net web api 2 identity provider.
If I am not using the roles or claims, can I exclude them from the query generated by the identity provider. This may help improve the performance a lot.
I am referring to the class ApplicationOAuthProvider.cs created by the default web api project.
The steps that it follows is:
var user1 = await userManager.FindByNameAsync(context.UserName);
if (user1 == null)
{
context.SetError("invalid_grant", "The user is not registered.");
return;
}
//Query gets executed once here
ApplicationUser user = await userManager.FindAsync(context.UserName, context.Password);
if (user == null)
{
context.SetError("invalid_grant", "The user name or password is incorrect.");
return;
}
// Query gets executed once again here
ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager,
OAuthDefaults.AuthenticationType);
//This one generates one more query
ClaimsIdentity cookiesIdentity = await user.GenerateUserIdentityAsync(userManager,
CookieAuthenticationDefaults.AuthenticationType);
//Fires the same query as above
AuthenticationProperties properties = CreateProperties(user.UserName);
AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, properties);
context.Validated(ticket);
context.Request.Context.Authentication.SignIn(cookiesIdentity);
THE WHOLE PROCESS TAKES 4 SECONDS. AM I DOING ANYTHING WRONG HERE?
Can we eliminate some process / merge few of them and optimize the
same.
Thanks
We sort of have the same setup.
Does it happen on every single request?
We've had quite alot of problems with entity framework cold queries and view generation, however, the "second" query always goes really fast.
If that is the case you can try using ADO.net with Identity instead and pregenerate views for entity framework. However, it's still a messy solution and something I really think MS should adress.
The article is still very relevant regarding identity, and there by entity framework, "warm-up".

Resources