accessing UI Thread with async / await with Mvvm - mvvm

I want to pass some contents on the DocumentViewer with progress indicator using Mvvm pattern, this generation will use UiElements after getting data from db asynchrounously.
public async void ProcessReportAsync(){
IsBusy = true;
_reportDal = new ReportDal(_sprocName,_sprocParams);
ReportContainers = new ObservableCollection<ReportContainerViewModel>();
await Task.Run(() => _reportDal.InitReportDal());
ReportDataTable = _reportDal.DataTableReport;
await Task.Run(() => ProcessedElements());
var t3 = Task.Run(() => ProcessPage(_reportPage));
var t4 = Task.Run(() => ProcessContainerData());
await Task.WhenAll(t3, t4);
var p = new PrinterViewModel(this);
// This statement does'nt complete its execuation, which is adding more UIElements
if(DispatcherHelper.UIDispatcher.CheckAccess()) {
DispatcherHelper.UIDispatcher.Invoke(
()=>_document = p.CreateDocument(new Size(p.PrintDialog.PrintableAreaWidth,p.PrintDialog.PrintableAreaHeight))
,DispatcherPriority.Background);
}
// Can't reach this code
IsBusy = false;
}

One nice aspect of async/await is that it takes care of dispatching back to the correct context for you.
public async Task ProcessReportAsync()
{
IsBusy = true;
_reportDal = new ReportDal(_sprocName,_sprocParams);
ReportContainers = new ObservableCollection<ReportContainerViewModel>();
await Task.Run(() => _reportDal.InitReportDal());
ReportDataTable = _reportDal.DataTableReport;
await Task.Run(() => ProcessedElements());
var t3 = Task.Run(() => ProcessPage(_reportPage));
var t4 = Task.Run(() => ProcessContainerData());
await Task.WhenAll(t3, t4);
var p = new PrinterViewModel(this);
_document = p.CreateDocument(new Size(p.PrintDialog.PrintableAreaWidth,p.PrintDialog.PrintableAreaHeight));
IsBusy = false;
}
I suggest you read my async/await intro and my MSDN article on async.

Related

How to update multiple rows of a database table in ASP.NET Core

I want to update multiple rows in ASP.NET Core, but I get an error:
InvalidOperationException: The entity type 'EntityQueryable' was not found. Ensure that the entity type has been added to the model.
This is my code:
var data = _db.UserTable.Where(a => a.CityIDn == selectedid);
foreach (var items in data)
{
await Task.Run(() =>
{
items.CityID = 2;
});
_db.Update(data);
await _db.SaveChangesAsync();
}
Try this for multiple rows:
var data = _db.UserTable.Where(a => a.CityIDn == selectedid).ToList();
foreach (var item in data)
{
item.CityID = 2;
_db.UserTable.Update(item);
}
await _db.SaveChangesAsync();
And for one record, try like this:
var data = _db.UserTable.Where(a => a.CityIDn == selectedid).FirstOrDefault();
if(data != null)
{
data.CityID = 2;
_db.UserTable.Update(data );
await _db.SaveChangesAsync();
}
The content of Update should be items, it worked for me, you can have a try.
var data = _db.UserTable.Where(a => a.CityIDn == selectedid).ToList();
foreach (var items in data)
{
await Task.Run(() =>
{
items.CityID = 2;
});
_db.Update(items);
await _db.SaveChangesAsync();
}

Why EF Core navigation properties doesnt fill?

I face a problem with below code
public async Task<IActionResult> Index()
{
var mainPageViewModel = new MainPageViewModel()
{
Walls = await _unitOfWork.Walls.GetAllAsync(),
PopularStoreProducts = await Context.Set<StoreProduct>().Include(sp => sp.Product).Include(sp => sp.Store).ToListAsync(),
Reviews = await _unitOfWork.Reviews.GetAllWithIncludeAsync()
};
var cartItems = await Context.Set<CartItem>().Include(ci => ci.StoreProduct).ThenInclude(sp => sp.Product)
.Include(ci => ci.StoreProduct).ThenInclude(sp => sp.Store).ToListAsync(); ;
return View(mainPageViewModel);
}
When I trace above code, cartItems.StoreProduct won't be null but an empty StoreProduct.
Everything will be fine when I remove this line:
PopularStoreProducts = await Context.Set<StoreProduct>().Include(sp => sp.Product).Include(sp => sp.Store).ToListAsync(),
My question is that why navigation properties sets empty when I already read that navigation properties in their one's queries.
Thanks in advance.

Transaction not working with Web API .net core 2.2

I have a async web API that has services and a connection to the db using an EF context.
In one of the services, where I inject the context using DI I want to make a simple transactional service, like:
public async Task<int> ServiceMethod()
{
using (var transaction = context.Database.BeginTransaction())
{
await context.Table1.AddAsync(new Table1());
await context.SaveChangeAsync();
CallOtherservice(context);
await context.SaveChangeAsync();
transaction.Commit();
}
}
CallOtherService(Context context)
{
await context.Table2.AddAsync();
}
I have now mocked CallOtherService() to throw an exception and I expect nothing to be commited, but it looks like changes to Table1 persist, amid the transaction trhat should stop them. I have tried calling Rollback() in a try catch statement and using a TransactionScope() instead, but both were useless. Also, I have noticed that after calling .BeginTransaction(), context.Database.CurrentTransaction is null, which I consider a bit weird.
EDIT:
the method that I test:
public async Task<int> AddMatchAsync(Models.Database.Match match)
{
//If match is null, nothing can be done
if (match == null)
return 0;
else
{
using (var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
{
try
{
//If the match already exists, return its id
var dbId = await ExistsMatchAsync(match.HomeTeam.Name, match.AwayTeam.Name, match.Time);
if (dbId > 0)
{
log.Info($"Found match with id {dbId}");
return dbId;
}
//add computable data
match = await AttachMatchName(match);
match.Season = CommonServices.toSeason(match);
// Prepare the relational entities accordingly
match = PrepareTeamsForAddMatch(match).Result;
match = PrepareLeagueForAddMatch(match).Result;
//add the match and save it to the DB
await context.Matches.AddAsync(match);
await context.SaveChangesAsync();
log.Info($"Successfully added a new match! id: {match.Id}");
// Create new TeamLeagues entities if needed
leaguesService.CreateTeamLeaguesForNewMatchAsync(context, match);
await context.SaveChangesAsync();
scope.Complete();
return match.Id;
}
catch (Exception ex)
{
log.Error($"Error adding match - Rolling back: {ex}");
throw;
}
}
}
}
and the test:
[Test]
public void AddMatchSaveChangesTransaction()
{
//Arrange
var exceptiontext = "This exception should prevent the match from being saved";
var leagueServiceMock = new Mock<ILeaguesService>();
leagueServiceMock.Setup(p => p.CreateTeamLeaguesForNewMatchAsync(It.IsAny<InFormCoreContext>(),It.IsAny<Match>()))
.Throws(new Exception(exceptiontext));
leagueServiceMock.Setup(p => p.GetLeagueAsync(It.IsAny<string>()))
.ReturnsAsync((string name) => new League{Id = 1, Name = name });
var match = new Match
{
HomeTeam = new Team { Name = "Liverpool" },
AwayTeam = new Team { Name = "Everton" },
League = new League { Name = "PL", IsSummer = true },
Time = DateTime.UtcNow,
HomeGoals = 3,
AwayGoals = 0
};
var mcount = context.Matches.Count();
//Act
var matchService = new MatchesService(context, leagueServiceMock.Object, new LogNLog(), TeamsService);
//Assert
var ex = Assert.ThrowsAsync<Exception>(async () => await matchService.AddMatchAsync(match));
Assert.AreEqual(ex.Message, exceptiontext);
Assert.AreEqual(mcount, context.Matches.Count(), "The match has been added - the transaction does not work");
}`
```

Moq MongoDB UpdateOneAsync method for unit testing

I want to moq update method that is using mongodbContext. here is what i am trying to do but its not working. how to pass UpdateResult return type .ReturnsAsync<UpdateResult>(). I am very new to Mongodb database Unit Testing with .net core.
public void UpdateEventAsync_Test()
{
//Arrange
var eventRepository = EventRepository();
var pEvent = new PlanEvent
{
ID = "testEvent",
WorkOrderID = "WorkOrderID",
IsDeleted = false,
IsActive = true,
EquipmentID = "EquipmentID"
};
////Act
mockEventContext.Setup(s => s.PlanEvent.UpdateOneAsync(It.IsAny<FilterDefinition<PlanEvent>>(), It.IsAny<UpdateDefinition<Model.EventDataModel.PlanEvent>>(), It.IsAny<UpdateOptions>(), It.IsAny<System.Threading.CancellationToken>())).ReturnsAsync<UpdateResult>();
var result = eventRepository.UpdateEventAsync(pEvent);
////Assert
result.Should().NotBeNull();
Assert.AreEqual(true, result);
}
below is the code for which i want to write Moq Test
public async Task<bool> UpdateEventAsync(Model.EventDataModel.PlanEvent eventobj)
{
var filter = Builders<Model.EventDataModel.PlanEvent>.Filter.Where(f => f.ID == eventobj.ID);
// TO Do: Use replace instead of update.
var updatestatement = Builders<Model.EventDataModel.PlanEvent>.Update.Set(s => s.IsDeleted, eventobj.IsDeleted)
.Set(s => s.EquipmentID, eventobj.EquipmentID)
.Set(s => s.PlannedStartDateTime, eventobj.PlannedStartDateTime)
.Set(s => s.PlannedEndDatetime, eventobj.PlannedEndDatetime)
.Set(s => s.WorkOrderID, eventobj.WorkOrderID)
.Set(s => s.ResourceID, eventobj.ResourceID)
.Set(s => s.LastUpdatedBy, eventobj.LastUpdatedBy)
.Set(s => s.EventComment, eventobj.EventComment)
.Set(s => s.SiteID, eventobj.SiteID)
.Set(s => s.LastUpdatedDateTime, DateTime.UtcNow.ToString());
UpdateResult updateResult = await _eventContext.PlanEvent.UpdateOneAsync(filter, updatestatement);
return updateResult != null && updateResult.IsAcknowledged && updateResult.ModifiedCount > 0;
}
Either create an instance or mock UpdateResult and return that from the setup
public async Task UpdateEventAsync_Test() {
//...omitted for brevity
var mockUpdateResult = new Mock<UpdateResult>();
//Set up the mocks behavior
mockUpdateResult.Setup(_ => _.IsAcknowledged).Returns(true);
mockUpdateResult.Setup(_ => _.ModifiedCount).Returns(1);
mockEventContext
.Setup(_ => _.PlanEvent.UpdateOneAsync(It.IsAny<FilterDefinition<PlanEvent>>(), It.IsAny<UpdateDefinition<Model.EventDataModel.PlanEvent>>(), It.IsAny<UpdateOptions>(), It.IsAny<System.Threading.CancellationToken>()))
.ReturnsAsync(mockUpdateResult.Object);
//Act
var result = await eventRepository.UpdateEventAsync(pEvent);
//Assert
result.Should().Be(true);
}
Also note that the test needs to be made async to be exercised accurately.

get office 365 mail in oldest first order using OutlookServiceClient

ResponseModel responseModel = new ResponseModel();
var contacts = new List();
OutlookServicesClient client = new OutlookServicesClient(new Uri("https://outlook.office.com/api/v2.0/"),
async() =>
{
return oValidationResponse.access_token;
});
try
{
var userDetail = await client.Me.Contacts.ExecuteAsync();
How I use it for OrderBy CreatedDateTime i.e
var userDetail = await client.Me.Contacts.OrderBy(x=>x.CreatedDateTime).ExecuteAsync();
this syntax gives error IContact not contain CreatedDateTime, so now I have no other way to use.
Based on the code you were retrieve the contacts. Here is an sample that retrieve the messages and order them with ReceivedDateTime.
OutlookServicesClient client = new OutlookServicesClient(new Uri("https://outlook.office.com/api/v2.0/"), () =>
{
return Task.Delay(10).ContinueWith(t => accessToken);
});
var Messages = client.Me.Messages.OrderBy(msg => msg.ReceivedDateTime).Take(20).ExecuteAsync().Result;
int i = 0;
foreach (var msg in Messages.CurrentPage)
{
Console.WriteLine($"({++i,-3}:){msg.Subject,-50}:\t{msg.ReceivedDateTime,-30}");
}
More detail about the mail rest refer to here.