MongoDb Update error: Maximum serialization depth exceeded - c#

I am new to Mongodb, so please execute if my question is elementary. I am using the Mongodb C# driver in my ASP.net MVC project. However, while executing the MongoDb C# update operation, I am hitting this error
Maximum serialization depth exceeded (does the object being serialized have a circular reference?).
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: MongoDB.Bson.BsonSerializationException: Maximum serialization depth exceeded (does the object being serialized have a circular reference?).
Here is the object model class. Is the error due to the below line, which is there in my model class?
public List OutGoingFriendRequestList { get; set; }
public class UserProfileViewModel
{
public ObjectId Id { get; set; }
public string UserId { get; set; }
public string Email { get; set; }
public string DisplayName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string UserDescription { get; set; }
public string UserName { get; set; }
public List<UserProfileViewModel> OutGoingFriendRequestList { get; set; }
}
}
And here is the Controller Action Method in which I try to do the update
public async Task<ActionResult> AddFriend(UserProfileViewModel model)
{
//Get the database connection instance and then get the collection
var _database = SocialNetworkHelper.ReturnMongoDbInstance();
IMongoCollection<UserProfileViewModel> collection =
_database.GetCollection<UserProfileViewModel>("Facebook_Lite");
//In the next 2 sentences, I am filtering using the userId field
string userId = User.Identity.GetUserId();
var filter = Builders<UserProfileViewModel>.Filter.Eq("UserId", User.Identity.GetUserId());
var result = collection.Find(filter).ToListAsync();
result.Wait();
UserProfileViewModel userProfileViewModelInstance = result.Result.ElementAt(0);
List<UserProfileViewModel> OutgoingFriendRequestList = userProfileViewModelInstance.OutGoingFriendRequestList;
OutgoingFriendRequestList.Add(friendUserModelInstance);
userProfileViewModelInstance.OutGoingFriendRequestList = OutgoingFriendRequestList;
var update = Builders<UserProfileViewModel>.Update.Set("OutGoingFriendRequestList", userProfileViewModelInstance.OutGoingFriendRequestList);
//I am hitting the exception on the below line
**var updateResult = await collection.UpdateOneAsync(filter, update);**
return RedirectToAction("Index", "Home", new { userid = friendUserId });
}

The way you represent a tree like model like yours is by holding references to children/leaves, not the objects themselves. Instead of:
public List<UserProfileViewModel> OutGoingFriendRequestList { get; set; }
you should store ids of these database redords.
public List<ObjectId> OutGoingFriendRequestList { get; set; }

Related

Mongo DB TypeInitializationException

I am trying to fetch data from inside mongodb.
I am getting the following exception:
System.TypeInitializationException: 'The type initializer for 'MongoDB.Bson.Serialization.BsonClassMap' threw an exception.'
ArgumentNullException: Value cannot be null. Arg_ParamName_Name
public IQueryable<IssueDto> FetchCollection(string databaseName, string collectionName)
{
var dbClient =
new MongoClient("mongo connection string here");
var database = dbClient.GetDatabase(databaseName);
var collection = database.GetCollection<IssueDto>(collectionName);
return collection.AsQueryable();
}
Json inside mongo:
{
"_id":{"$oid":"63920bcf14ab25ab93444804"},
"name":"This is a task",
"completed": true,
"issueId":1234
}
The model class is as follows:
public class IssueDto
{
[BsonElement("_id")]
public ObjectId Id { get; set; }
[BsonElement("issueId")]
public int IssueId { get; set; }
[BsonElement("name")]
public string Name { get; set; }
[BsonElement("completed")]
public bool Completed { get; set; }
}
Can anyone spot what is going wrong?
Other info: .NET6, MongoDB.Driver 2.8.0

Entity Framework won't add children to parent object

The api response returns as if the function ran without problems but when i look the database the row simple is not there.
I don't get any error messages.
Even if I try to add one exam directly through _context.Exames it won't add.
I'm getting really frustrated because I don't even know where or what I should look for as the api returns that the method run successfully
I'm using ASP.NET Core 5 and EF Core with MySQL.
Here is the code:
public class Account
{
public int Id { get; set; }
public string Title { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public string PasswordHash { get; set; }
public List<Exame> Exames { get; set; }
public List<Consulta> Consultas { get; set; }
}
public class Exame
{
[Key]
public int ExameID { get; set; }
public long Image { get; set; }
}
public class DataContext : DbContext
{
public DbSet<Account> Accounts { get; set; }
public DbSet<Exame> Exames { get; set; }
}
[HttpPost("exame")]
public IActionResult CreateExame(ExameRequest exame)
{
_accountService.CreateExame(exame);
return Ok(new { message = "Exame added successfully" });
}
public void CreateExame(ExameRequest model)
{
var account = _context.Accounts.SingleOrDefault(x => x.Id == model.AccountId);
var exame = new Exame();
exame.ExameID = model.Id;
exame.Image = model.Image;
if (account.Exames == null)
{
account.Exames = new List<Exame>();
}
account.Exames.Add(exame);
_context.Accounts.Update(account);
_context.SaveChangesAsync();
}
It looks like it's returning before the Save has finished, try altering it to something like:
[HttpPost("exame")]
public Task<IActionResult> CreateExame(ExameRequest exame)
{
var result = await _accountService.CreateExame(exame);
// check the value and return the appropriate message.
return Ok(new { message = "Exame added successfully" });
}
public async Task<int> CreateExame(ExameRequest model)
{
// removed other code
return await _context.SaveChangesAsync();
}
Since the call to SaveChangesAsync() is async, the code is making the call and moving straight back to the api call and returning OK. The result of the SaveChangesAsync is as follows.
A task that represents the asynchronous save operation. The task
result contains the number of state entries written to the underlying
database. This can include state entries for entities and/or
relationships. Relationship state entries are created for many-to-many
relationships and relationships where there is no foreign key property
included in the entity class (often referred to as independent
associations).
I have the same problem as I am following a course.
it is probably a versioning problem, cause my code is exactly the same as the instructor but I can't get the result I want.
I think it is because of Microsoft.EntityFrameworkCore.InMemory version.
the 5th version apparently don't have this problem but 7 does.

how to fetch data in mongoDb using Asp.net with button click and I know username only

I am facing problem in asp.net for fetching data from MongoDB and got an error. Please help me to resolve this error.
Error :
Cannot deserialize a 'ObjectId' from BsonType 'Null'.Description: An
unhandled exception occurred during the execution of the current web
request. Please review the stack trace for more information about the
error and where it originated in the code.
Exception Details:
System.FormatException: Cannot deserialize a 'ObjectId' from BsonType
'Null'.
public partial class Loginpage : System.Web.UI.Page
{
protected void Button1_Click(object sender, EventArgs e)
{
String connectionstring = "mongodb://localhost";
var client = new MongoClient(connectionstring);
var database = client.GetDatabase("SIH");
bool isMongoLive = database.RunCommandAsync((Command<BsonDocument>)"{ping:1}").Wait(1000);
if (isMongoLive)
{
var collection = database.GetCollection<userinfo>("userinfo");
// var id = new ObjectId("5a6b35217e60af482bedef33");
var idd = TextBox1.Text;
//var userinfo = collection.Find(b => b._id == id).ToListAsync().Result;
var userinfo = collection.Find(b => b.name == idd).ToListAsync().Result; // Due to this i got an error
foreach (var user in userinfo)
{
Response.Write(user.phoneno);
}
}
else
{
Response.Write("Hello dude your server is not connected !! ");
}
}
}
public class userinfo
{
//public ObjectId _id { get; set; }
public string name { get; set; }
public string emailid { get; set; }
public string password { get; set; }
public string phoneno { get; set; }
public string activate { get; set; }
public string block { get; set; }
}
Seems like in SIH collection one of your documents has a null ObjectId
You can make your code work by making _id nullable public ObjectId? _id { get; set; }

linq query to DB returns model with list, when model is ok but list is empty

This drives me crazy I have mode with list of two other models in it. As long as I had there iCollections it worked fine, but I had to change them to List, because I need to export the data into XML.
Model
public class PortalUser
{
//private List<UserToTeam> UserToTeam_ = new List<UserToTeam>();
//private List<Mandays> Mandays_ = new List<Mandays>();
public int ID { get; set;}
public string Name { get; set; }
[DisplayName("Last Name")]
public string LastName { get; set; }
public Role Role { get; set; }
//public virtual ICollection<Mandays> Mandays { get; set; }
public List<Mandays> Mandays { get; set; } //{ return Mandays_; }
[DisplayName("Team")]
//public virtual ICollection<UserToTeam> UserToTeam { get; set; }
public List<UserToTeam> UserToTeam { get; set; } //{ return UserToTeam_; }
public PortalUser()
{
Mandays = Mandays ?? new List<Mandays>();
UserToTeam = UserToTeam ?? new List<UserToTeam>();
}
Then I use this to get data from the DB
List<PortalUser> dbAgent = db.PortalUser.ToList();
End while debugging the result ends as Count = 0. While iCollection return the model within model correctly the List always returns Count = 0. In DB Users have Mandays and even team, but result is always empty.
I am sure I am missing something simple, please help. I can post more code if needed.
I am not sure if EF supports a List collection like that, however you need the virtual keyword in there so EF can create wrapped collections appropriately.

Web Service Exception: "The formatter threw an exception while trying to deserialise the message"

Got a question. I get this error and I know it is due to the fact that int32 has a number limit of 2147483647. But I don't know why I am getting this error when the value in question (a telephone number of 11 digits) is defined as a string in our SQL database, a string in our web service and a string in our web application.
I assume it is something to do with the way the service serialises and deserialises data over a connection, but I was wanting to know if there is a way to force Number to use only the string instead of parsing it when deserialisation happens. Or even get it to parse as int64.
Here is the error exception. I removed the namespace and service name. It is the property Number that is causing the problem.
There was an error deserializing the object of type .".ClientPhone[]. The value '07721545554' cannot be parsed as the type 'Int32'."
And here is the code for the service and the service interface.
[DataContract]
public class ClientPhone
{
[DataMember]
public int? ClientNumberID { get; set; }
[DataMember]
public int? RefID { get; set; }
[DataMember]
public string Number { get; set; }
[DataMember]
public string NumberType { get; set; }
[DataMember]
public bool? PrimaryNumber { get; set; }
}
public partial class ClientNumberEntity
{
public int ClientNumbersID { get; set; }
public Nullable<int> RefID { get; set; }
public string ClientNumberType { get; set; }
public string ClientNumber { get; set; }
public Nullable<bool> PrimaryNumber { get; set; }
public virtual ClientDataEntity ClientData { get; set; }
}
public List<ClientPhone> GetClientsPhoneByReference(int _reference)
{
OurDatabaseEntities context = new OurDatabaseEntities();
var phoneEntity = (from c in context.ClientNumberEntities
where c.RefID == _reference
select c).ToList();
if (phoneEntity != null)
{
return TranslateClientPhoneEntityToPhoneNumberList(phoneEntity);
}
else
throw new Exception("Unable to get phone data");
}
private List<ClientPhone> TranslateClientPhoneEntityToPhoneNumberList(List<ClientNumberEntity> numberEntities)
{
List<ClientPhone> phoneList = new List<ClientPhone>();
foreach (ClientNumberEntity numberEntity in numberEntities)
{
ClientPhone phoneListMember = new ClientPhone();
phoneListMember.ClientNumberID = numberEntity.ClientNumbersID;
phoneListMember.RefID = numberEntity.RefID;
phoneListMember.Number = numberEntity.ClientNumber;
phoneListMember.NumberType = numberEntity.ClientNumberType;
phoneListMember.PrimaryNumber = numberEntity.PrimaryNumber;
phoneList.Add(phoneListMember);
}
return phoneList;
}
Any advice on a solution would be greatly appreciated! Thanks :)
Got a solution, albeit it's more stupidity on my end.
I didn't realise that my .EDMX entity diagram hadn't been updated with the new values from the database (I had to manually delete the entity and re-add it to force changes).
After re-compiling and updating the service reference, it worked.

Categories

Resources