Can't insert data in mongodb with insertOneAsync - c#

I want to insert data into a mongodb database. It worked like a charm, but I have one collection where I can't insert in the database and I don't know why. I do literally the same.
This doesnt work here
public async Task AddVerifyAsync(VerifyModel verifyModel)
{
verifyModel.CreationDate = DateTime.Now;
await _context.Verifies().InsertOneAsync(verifyModel);
}
I checked it multiple times, ran the debug mode, checked the model etc, it is all absolutely correct.
This is the method which returns the collection:
public IMongoCollection<VerifyModel> Verifies()
{
return _database.GetCollection<VerifyModel>("VerifyModel");
}
These are the methods that are working:
public async Task AddUserAsync(UserModel user)
{
await _context.Users().InsertOneAsync(user);
}
The collection-returner is just the same as above but with the other types.
I even have tried to remove the DateTime thing. Also I set the _id before giving it to the AddVerifyAsync method. But I even have tried disabling that.
the _context is dependency injected in the constructor.
This is where both methods get used:
public async Task CreateUserAsync(UserModel user)
{
UserModel gotUser = await _userRepository.GetUserByEmailAsync(user.Email);
//check if exists
if (gotUser != null)
throw new DataException();
//set defaults and prevent, that the user tries to manipulate data
user.Active = false;
user.RegTimeStamp = DateTime.Now;
user.AdminLevel = 0;
user.OrganizationId = null;
user.OrganizationAdminLevel = null;
user.Password = BCrypt.Net.BCrypt.HashPassword(user.Password);
user.Balance = 0f;
user.ProfilePicture = "";
//Add the user to the repo
await _userRepository.AddUserAsync(user);
VerifyModel verifyModel = new VerifyModel();
verifyModel.UserId = user.Id;
verifyModel.Id = ObjectId.GenerateNewId().ToString();
//useractivation
verifyModel.Type = 0;
//insert the verifyuser in database
await _verifyRepository.AddVerifyAsync(verifyModel);
await _emailSenderService.SendMailAsync(user, EmailTemplate.RegisterMail, verifyModel.Id,
"Herzlich Willkommen bei flundr. Nur noch ein Schritt!", user.Email);
}
Here the Verifymodel doesnt get inserted in the db.

Related

Firestore.Query.GetSnapshotAsync() never returns and doesn't give any errors - the program just doesn't stop

I'm building a game in Unity version 2019.4.1f1 (LTS) and i'm using Firebase Firestore database.
Basically when I try to fetch the user from the database, specifically when i'm calling GetSnapshotAsync(), it gets stuck.
The hierarchy is as follows:
StartState calls FetchUserState which calls DBGetObjectState which communicates with DatabaseManager (DatabaseManager contains the line where GetSnapshotAsync() gets called).
Would be really nice if someone could help me figure out this problem.
Thank you for helping!
class FetchUserState
//fetch user by userId
await stateManager.PushTempState(new DBGetObjectState<T>(StringConstants.DB_USERS_COLLECTION, //("Users")
field: "UserId", fieldEqualTo: _userId, withLoading: false));
class DBGetObjectState
Log("Getting Documents");
var documents = await DatabaseManager.GetDocuments<T>(_path, _limit, _orderBy, _orderByDescending, _field, _fieldEqualTo);
Log("Got something, checking..."); // doesn't get here
class DatabaseManager
public static async Task<Collection<T>> GetDocuments<T>(string path, int limit = -1,
string orderBy = null, string orderByDescending = null, string field = null, object fieldEqualTo = null)
{
var collectionRef = DBUtills.GetCollectionRef(path);
Query query = collectionRef;
if (field != null && fieldEqualTo != null)
query = query.WhereEqualTo(field, fieldEqualTo);
if (orderBy != null)
query = query.OrderBy(orderBy);
if (orderByDescending != null)
query = query.OrderByDescending(orderByDescending);
if (limit >= 0)
query = query.Limit(limit);
Debug.Log("Snapshotting!");
QuerySnapshot collectionSnapshot = await query.GetSnapshotAsync();
Debug.Log("got a snapshot, checking..."); // doesn't get here
//....
}
Thanks to anyone who tried to help, apparently it was a plugin that I used for handling tasks, I should've checked it first before even asking the question.
Anyways, if someone still experiences an issue, #derHugo's answer was definitely a solution, instead of awaiting the task, simply use ContinueWithOnMainThread() to create a callback that will be called after the task is finished, like that:
query.GetSnapshotAsync().ContinueWithOnMainThread(task =>
{
if(task.IsFaulted)
{
//....
}
QuerySnapshot collectionSnapshot = task.Result;
//....
}

Entity framework error : Cannot access a disposed object

In my method below which is written using c# in asp.net core, I am getting error when executing any of the below update statements. What is the issue with using await SaveContextAsync(); I have noticed I dont get error when only using SaveContext();
The error that I am getting is as follows
Cannot access a disposed object. A common cause of this error is disposing a context that was resolved from dependency injection
and then later trying to use the same context instance elsewhere in your application. This may occur if you are calling Dispose()
on the context, or wrapping the context in a using statement. If you are using dependency injection, you should let the dependency
injection container take care of disposing context instances.
Object name: 'FXDB1Context'.
I am not sure why I am getting this error.
public async Task<IdentityResult> ApproveUserChangeRequest(UserChangeRequest userChangeRequest, string approvedByAuthUserName, string authApplicationName)
{
var userChangeRequestRepository = UserChangeRequestRepository.GetAllAsList();
var userChangeRequestApprovalRepository = UserChangeRequestApprovalRepository.GetAllAsList();
var appSettingRepository = AppSettingRepository.GetAllAsList();
var clientCompanyContactRepository = ClientCompanyContactRepository.GetAllAsList();
var applicationUserRepo = ApplicationUserRepo.GetAllAsList();
int approvedByAuthUserID = GetApprovedByUserId(authApplicationName, approvedByAuthUserName);
// Check if UserChangeRequest is still Pending
bool isUserChangeRequestPending = userChangeRequestRepository.Any(x => x.Id == userChangeRequest.Id && x.ChangeStatus == "Pending");
if (isUserChangeRequestPending && approvedByAuthUserID > 0)
{
// Inserting record in the UserChangeRequestApproval table
InsertUserChangeRequestApproval(userChangeRequest);
await SaveContextAsync();
using (var userTransaction = Context.Database.BeginTransaction())
{
using (var securityTransaction = _securityContext.Database.BeginTransaction())
{
try
{
//Get the Number of approval required for Internal and External Users
int? internalApprovalsRequired = GetApprovals("InternalUserChangeRequestApprovalsRequired", appSettingRepository);
int? externalApprovalsRequired = GetApprovals("ExternalUserChangeRequestApprovalsRequired", appSettingRepository);
//Get the name of the application the auth user belongs to
var authUserApplicationName = GetApplicationName(userChangeRequest.AuthUserId);
//Get the Number of approvals for the request
var numberOfAprovals = userChangeRequestApprovalRepository.Where(x => x.UserChangeRequestId == userChangeRequest.Id).Count();
//If the number of approvals is equal or greater than the Approvals required then Update AppUser or Contact details
if ((authUserApplicationName == "ArgentexTrader" && numberOfAprovals >= internalApprovalsRequired) || (authUserApplicationName == "ArgentexClient" && numberOfAprovals >= externalApprovalsRequired))
{
//Updating the clientcontact table
UpdateClientContact(userChangeRequest, clientCompanyContactRepository);
//Updating the auth user table
UpdateAuthUser(userChangeRequest);
//Updating the IdentityDB user table
UpdateIdentityDBUser(userChangeRequest, applicationUserRepo);
//Updating the UserChangeRequest table
userChangeRequest.ChangeStatus = "Approved";
UserChangeRequestRepository.Update(userChangeRequest);
await SaveContextAsync();
userTransaction.Commit();
securityTransaction.Commit();
return IdentityResult.Success;
}
}
catch (Exception ex)
{
userTransaction.Rollback();
securityTransaction.Rollback();
_logger.Error(ex);
return IdentityResult.Failed(new IdentityError { Description = ex.Message });
}
}
}
}
return null;
}
The error says that a resolved context is been trying to made Disposable.
For More Information: Using Statements in C#
using statement is a scope only process, so this error means that your program tries to use the same instances of "context" in somewhere else, which it cant use it, because as I mentioned it is a "scope only" process.
In your example:
using (var userTransaction = Context.Database.BeginTransaction())
{
using (var securityTransaction = _securityContext.Database.BeginTransaction())
{
}
}
You can make it simple and dont use a using scope or you can be sure that, the context is just used in those using scopes.

MCV C# web-service with POST and two variables

i am kinda new with the web services regarding to POST and i want to save the userId that i get from Owin and the id_cd in the favorite table. The webservice posted below is working however there is not need from me to get the return UserProvider back. The whole section ListAspNetUserLogins ... etc. is not needed but i can't seem to find a POST that allows me to add the two variables. What do i need to change to still have the two variables come in and get rid of the return UserProvider etc.
[Route("api/User/PostUserFavorite/{id_cd}/{UserId}")]
public async Task<List<AspNetUserLogins>> PostUserFavorite(int id_cd, string UserId)
{
User_FavoriteCd newEntry = new User_FavoriteCd();
newEntry.id_id = id_cd;
newEntry.datetime = DateTime.Now;
newEntry.UserId = UserId;
db.User_FavoriteCd.Add(newEntry);
db.SaveChanges();
List<AspNetUserLogins> UserProvider = await db.AspNetUserLogins
.Where(up => up.UserId == UserId)
.ToListAsync();
return UserProvider;
}
If you do not need a return value you can do:
[Route("api/User/PostUserFavorite/{id_cd}/{UserId}")]
public async Task PostUserFavorite(int id_cd, string UserId)
{
User_FavoriteCd newEntry = new User_FavoriteCd();
newEntry.id_id = id_cd;
newEntry.datetime = DateTime.Now;
newEntry.UserId = UserId;
db.User_FavoriteCd.Add(newEntry);
await db.SaveChangesAsync();
}

Updating Entity in EF6 gives primary key exception

When I try to update this object in EF6 I get an error stating more than 1 entity has this primary key. Looking at this DB I know this to be untrue(from what I can see).
I need to be able to update a second object based on one of the properties on the posted object. The code below produces the error. I have left in commented out pieces that I have tried to get this to work.
public async Task<ActionResult> Edit(PricingRule pricingRule)
{
if(ModelState.IsValid)
{
var currentUser = await serv.UserManager.FindByIdAsync(User.Identity.GetUserId());
var company = currentUser.Company;
//var entityRule = serv.PricingService.PricingRules.Get(pricingRule.PricingRuleId);
//If this is the first rule, set it to the company default
var rulesCount = company.PricingRules.Count;
if (rulesCount <= 1 || company.DefaultPricingRule == null)
pricingRule.DefaultPricingRule = true;
//Make sure no other rules are marked as default, and update the company with this rule as default
if (pricingRule.DefaultPricingRule)
{
if (company.DefaultPricingRule != null)
{
var oldRule = serv.PricingService.PricingRules.Get(company.DefaultPricingRule.PricingRuleId);
oldRule.DefaultPricingRule = false;
//serv.PricingService.PricingRules.Update(oldRule);
}
company.DefaultPricingRule = pricingRule;
serv.CoreService.Companies.Update(company);
}
serv.PricingService.PricingRules.Update(pricingRule);
await serv.SaveAllChangesAsync();
return RedirectToAction("Index");
}
return View(pricingRule);
}
Whether or not it is the best practice or how it should technically be done, this is how I solved my problem.
The edited object I was passing in, needed to be marked as modified first, before doing any other operations. I am assuming this is because the context could then grab it and all other operations regarding it would be done "within context". Other wise I think it was trying to add a new object if I tried to attach it to company.DefaultPricingRule.
public async Task<ActionResult> Edit(PricingRule pricingRule)
{
if(ModelState.IsValid)
{
serv.PricingService.PricingRules.Update(pricingRule);
var currentUser = await serv.UserManager.FindByIdAsync(User.Identity.GetUserId());
var company = currentUser.Company;
//If this is the first rule, set it to the company default
var rulesCount = company.PricingRules.Count;
if (rulesCount <= 1 || company.DefaultPricingRule == null)
pricingRule.DefaultPricingRule = true;
//Make sure no other rules are marked as default, and update the company with this rule as default
if (pricingRule.DefaultPricingRule)
{
if (company.DefaultPricingRule != null)
{
var oldRule = serv.PricingService.PricingRules.Get(company.DefaultPricingRule.PricingRuleId);
oldRule.DefaultPricingRule = false;
serv.PricingService.PricingRules.Update(oldRule);
}
company.DefaultPricingRule = pricingRule;
serv.CoreService.Companies.Update(company);
}
await serv.SaveAllChangesAsync();
return RedirectToAction("Index");
}
return View(pricingRule);
}
If Anyone has a comment on if this is best practice or if there is a better way to do it, I gladly take criticism.

Which one of these async calls is not like the other?

I suspect I have a deadlock issue, but it's an odd one that I can't rationalize. I have an API that needs to verify a few things in order to process the call. As part of the business logic, I might have to make more of those same calls as well. In this case, if a particular piece of data associated with an entity is not found, we attempt to use a backup (if one is configured), which requires checking other entities. Eventually, the code will hang.
Let's just dive into the code (comments highlight the calls in question).
API Controller:
public async Task<HttpResponseMessage> Get(int entityID, string content, bool? useBackUp = true)
{
//Some look-ups here, no issues at all
//This works, but it's this method that has an issue later in the process.
SystemEntity entityObj =
await BusinessLayer.GetSystemEntityAsync(SystemEntityID);
if (entityObj == null)
{
return new HttpResponseMessage
{
StatusCode = System.Net.HttpStatusCode.BadRequest,
Content = new StringContent("Entity is unavailable.")
};
}
string text = BusinessLayer.GetContentTextAsync(entityID
new List<string> {contentName}, useBackUp).Result.FirstOrDefault().Value;
if (text == null)
{
return new HttpResponseMessage {StatusCode = System.Net.HttpStatusCode.NoContent};
}
return new HttpResponseMessage
{
StatusCode = System.Net.HttpStatusCode.OK,
Content = new StringContent(text)
};
}
Business Layer:
public async Task<Dictionary<string, string>> GetContentTextAsync(int systemEntityID, List<string> contentNames, bool useBackUp)
{
Dictionary<string, string> records = new Dictionary<string, string>();
//We iterate for caching purposes
foreach (string name in contentNames)
{
string nameCopy = name;
string record = Cache.GetData(
string.Format("{0}_{1}_{2}", CONTENT, systemEntityID, name), () =>
DataLayer.GetCotnent(systemEntityID, nameCopy));
if (record == null && useBackUp)
{
List<int> entityIDs = new List<int> {systemEntityID};
int currentEntityID = systemEntityID;
//Here's that method again. This call seems to work.
SystemEntity currentEntity = await GetSystemEntityAsync(systemEntityID);
if (currentEntity != null && currentEntity.BackUpID.HasValue)
{
currentEntityID = (int) currentEntity.BackUpID;
}
while (!entityIDs.Contains(currentEntityID))
{
int id = currentEntityID;
record = Cache.GetData(
string.Format("{0}_{1}_{2}", CONTENT, systemEntityID, name), () =>
DataLayer.GetCotnent(id, nameCopy));
if (record != null) break;
entityIDs.Add(currentEntityID);
//This call seems to cause the deadlock
currentEntity = await GetSystemEntityAsync(currentEntityID);
if (currentEntity != null && currentEntity.BackUpID.HasValue)
{
currentEntityID = (int) currentEntity.UseBackupID;
}
}
}
if (record != null)
{
records.Add(name, record);
}
}
return records;
}
public async Task<SystemEntity> GetSystemEntityAsync(int systemEntityID)
{
SystemEntity systemEntity = await DataLayer.GetSystemEntity(
scc => scc.SystemEntityID == systemEntityID);
return systemEntity;
}
Data Layer:
public async Task<SystemEntity> GetSystemEntity(Expression<Func<SystemEntity, bool>> whereExpression)
{
using (EntityContext dbContext = createDbInstance())
{
//This is the last line that the debugger in VS 2013 brings me to. Stepping into this returns to whatever called the API method, waiting endlessly.
return await
dbContext.SystemEntity.Include(sc => sc.OtherEntity).Where(whereExpression).FirstOrDefaultAsync();
}
}
To recap: I call GetSystemEntityAsync three times. The first two times, it completes successfully. The third time, it hangs. If I comment out the first two calls so they don't run at all, the third one still hangs. If I remove the await and use just a normal FirstOrDefault in the return statement of the data layer method, then everything completes just fine.
Note: I have to keep the GetSystemEntityAsync method asynchronous. I cannot alter it to be synchronous.
What are the possible sources of the deadlock I'm encountering? I'm out of ideas on how to solve it.
Which one of these async calls is not like the other?
This one, I suspect:
string text = BusinessLayer.GetContentTextAsync(entityID
new List<string> {contentName}, useBackUp).Result.FirstOrDefault().Value;
Try changing it to this:
string text = (await BusinessLayer.GetContentTextAsync(entityID
new List<string> {contentName}, useBackUp)).FirstOrDefault().Value;
The possible source of the deadlock is described by Stephen Cleary in his "Don't Block on Async Code" blog post.

Categories