How to use manual references when inserting and retrieving relational data using MongoDb and its C# driver

126 views Asked by At

As it may be obvious of my question, I am coming from a relational database way of thinking (SQL server) and using ORMs (Entity Framework). I want to do the same things now in MongoDB and I am having some troubles with it.

Let me explain a simple scenario. Suppose we have a user, and each user can write some posts (a one-to-many relationship in SQL). So we are working with a simple case.

I've read two or three articles (and the MongoDB's original documentation) about when to use Manual References and DBRefs and when to just embed the documents within each other. And here as we are going to be needing posts without its users (like when a visitor of a website wants to see all the posts) and also users without the posts (like managing user profiles or something), I strongly believe that these two entities (documents) should be separated.

Now let's get our hands a little dirty with some code. What I do in entity framework to implement the idea above is something like this:

//user model
public class User 
{
    public int Id { get;set; }
    public string Name { get; set; }
    public List<Post> Posts { get; set; }

    public User
    {
        this.Posts = new List<Post>();
    }
}

//post model
public class Post
{
    public int Id { get; set; }
    public string Body { get; set; }
    public DateTime DateCreated { get; set; }
    public User User { get; set; }
}

//getting the data is pretty easy using entity framework
//suppose the context is created beforehand
var usersAndTheirPosts = context.Users.Include(x => x.Posts).Where(x => x.Id > 5).ToList();

//getting the first users post
List<Post> firstUserPosts = usersAndTheirPosts.FirstOrDefault().Posts;

//updating the posts that have been created after date x
foreach (var post in firstUsersPosts.Where(x => x.DataCreated > DateX))
{
    //do something with the posts
}
context.SaveChanges();  //the actual updating happens here

What I tried to do to implement the same thing in MongoDB was something like this (I am trying to use Manual References since I don't think DBRefs are a way to go for my scenario (additional unwanted overload):

//user class
public class User
{
    [BsonId]
    public ObjectId Id { get; set; }

    [BsonElement("name")]
    public string Name { get; set; }

    [BsonElement("posts")]
    [BsonIgnoreIfNull]
    public List<Post> Plants { get; set; }
}

//
public class Post
{
    [BsonId]
    public ObjectId Id { get; set; }

    [BsonElement("body")]
    public string Body { get; set; }

    [BsonElement("date_created")]
    public DateTime DateCreated { get; set; }

    [BsonElement("users_id")]
    public User User { get; set; }
}

//do other stuff that should be done

But of course, this scheme is not working and inserting a document of type User for example, causes the creation of very wired objects and documents (obviously)

So my ultimate question is this: How can I achieve the same functionality that I had in entity framework in MongoDB using Manual References and in short be able to do these two things:

  1. Somehow to select the users and their posts together as above (the Include method) using a filter and Deserialize it into one User object
  2. Get a user's posts and a post's user like implemented in the models that entity framework uses

Thanks in advance

0

There are 0 answers