I'm working on a project where the MongoDB model will be similar to Facebook. So we all know how FB works, a user "likes" a band/company page, and that user will see all the posts from that page.
Is the below model how I should design this?
If a Page has million likes, then each Post will have a million sub documents of Like. That does not seem right, there must be a better way that I cant think of.
Thanks.
public class Person
{
public ObjectId Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class Page
{
public ObjectId Id { get; set; }
public string Name { get; set; }
public List<Like> PersonLikes { get; set; }
}
public class Like
{
public ObjectId Id { get; set; }
public ObjectId UserId { get; set; }
public DateTime DateLiked { get; set; }
}
public class Post
{
public ObjectId Id { get; set; }
public ObjectId PageId { get; set; }
public string Message { get; set; }
public List<Like> PersonLikes { get; set; }
}
My take assuming you only want to track likes
public class Page
{
public ObjectId Id { get; set; }
public DateTimeOffset Date { get; set; }
public string Name { get; set; }
public int NumberOfLikes { get; set; }
}
public class Post
{
public ObjectId Id { get; set; }
public ObjectId PageId { get; set; }
public DateTimeOffset Date { get; set; }
public string Message { get; set; }
public int NumberOfLikes { get; set; }
}
I would then queue the Reaction (Like or Dislike) for insertion, "sentiment" information doesn't have to be stored in real time, does it? These are not medications, bank transactions, etc.
public class Like
{
public ObjectId Id { get; set; }
public ObjectId ParentId { get; set;}
public ObjectId UserId { get; set; }
public DateTimeOffset Date { get; set; }
}
Queue where? to a collection of Likes. Why not part of the page or post? Because if a post goes viral (as you said even though the majority won't), you may end up with a 1,000,000 likes. Who is going to browse this information other than an analytic engine?
You also have to ensure a user can only express their reaction only once per item.
The post only exists on one page so it´s the page that should own the post, not the post owning the page.
public class Person
{
public ObjectId Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class Page
{
public ObjectId Id { get; set; }
public string Name { get; set; }
public List<Like> PersonLikes { get; set; }
public List<Post> Posts { get; set; }
}
public class Post
{
public ObjectId Id { get; set; }
public string Message { get; set; }
public List<Like> Likes { get; set; }
}
public class Like
{
public ObjectId Id { get; set; }
public ObjectId UserId { get; set; }
public DateTime DateLiked { get; set; }
}
Related
I have a web page that allows user to sign petitions, in the user detail page I want to display the petitions the user has signed, including the petition image. The image is specific to the category of the petition.
I have a category model that holds the image
public class Category
{
public int CategoryID { get; set; }
public string Name { get; set;}
public string catImage { get; set; }
public ICollection<Cause> Causes { get; set; }
}
Then I have a cause model that links to the Category through CategoryID
public class Cause
{
public int CauseID { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public int UserID { get; set; }
public string createdBy { get; set; }
public DateTime createdOn { get; set; }
public int Target { get; set; }
public int CategoryID { get; set; }
public virtual ICollection<Signature> Signatures { get; set; }
public Category Category { get; set; }
}
Then a signature model that links the Cause to the User
public class Signature
{
public int SignatureID { get; set; }
public int CauseID { get; set; }
public int UserID { get; set; }
public DateTime signedOn { get; set; }
public virtual Cause Cause { get; set; }
public virtual User User { get; set; }
}
And finally a user model
public class User
{
public int ID { get; set; }
public string Username { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public string UserImage { get; set; }
public Role Role { get; set; }
public virtual ICollection<Signature> Signatures { get; set; }
}
On the user details page I am trying to display a table with a list of all the petitions the user has signed. I have been able to show the name and the date shown, but not the images.
I would really appreciated any help.
Thanks
I'm starting making experience with the EF Code-First and also WCF Service and run into a problem I could not solve with all the guides about this issue:
I got the following code structure
[DataContract]
public class Feed
{
public int Id { get; set; }
public int LanguageId { get; set; }
public int CategoryId { get; set; }
public int TypeId { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public string Description { get; set; }
[DataMember]
public FeedCategory Category { get; set; }
[DataMember]
public FeedType Type { get; set; }
[DataMember]
public string FeedUrl { get; set; }
[DataMember]
public Language Language { get; set; }
}
[DataContract]
public class FeedCategory
{
public int Id { get; set; }
[DataMember]
public string Name { get; set; }
public DateTime Registered { get; set; }
[DataMember]
public IList<Feed> Feeds { get; set; }
}
[DataContract]
public class FeedType
{
public int Id { get; set; }
[DataMember]
public string Name { get; set; }
public DateTime Registered { get; set; }
public IList<Feed> Feeds { get; set; }
}
[DataContract]
public class Language
{
public int Id { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public string CountryName { get; set; }
[DataMember]
public string CountryCode { get; set; }
[DataMember]
public string ShortCountryCode { get; set; }
}
But when I want to get all the feeds, all dependencies won't be received, so Category, Type & Language is null and I have no idea how to solve it.
Does anyone else knows how to do it?
I'm going to try and answer your question correctly based on my experience (from awhile ago as my company doesn't use EF anymore).
First you may need to apply a key to your entities. I did this in the OnModelCreating method.
modelBuilder.Entity<FeedType>().HasKey(k => k.Id );
Second I believe you have to set the mappings between these entities also able to be done in your OnModelCreating method.
modelBuilder.Entity<FeedType>().HasRequired<Feed>(h => h.Feed).WithOptional(x => x.FeedType);
Finally your need to enable eager loading or use the .Include on your query so that the child object is retrieved when the parent is.
All corrections welcome as it has been awhile.
I've got a little problem with my database design in an EntityFramework6 project. These are my two code first classes I use to create the database with. As you can see the Details class violates all normal forms out there and I want to split it up properly, however I have no idea how to do it properly, since I am totally new to SQLServer and EF.
So what is the best way to get a decent database design which I then could query?
internal class LocationDataContract
{
[Key]
public Guid Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public DbGeography Coordinates { get; set; }
public LocationsDetailsDataContract Details { get; set; }
}
internal class LocationDetailsDataContract
{
[Key, ForeignKey("Location")]
public Guid Id { get; set; }
public string Planet { get; set; }
public bool? IsCapital { get; set; }
public int Population { get; set; }
public string System { get; set; }
public string Sector { get; set; }
public LocationDataContract Location { get; set; }
}
Updated Question below
So following the advice of George I did the following. Would this be a decent solution. I Have to add, that I need to to some converting since the application uses different (completely inheritance based) models, which I have to use since a database is not the only source of data and said data uses yet another format to store data which I can't change.
internal class LocationDataContract
{
[Key]
public Guid Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public DbGeography Coordinates { get; set; }
public LocationsDetails Details { get; set; }
}
internal abstract class LocationDetailDataContract
{
[Key, ForeignKey("Location")]
public Guid Id { get; set; }}
public LocationsDetails Details { get; set; }
}
internal class CityDetailDataContract : LocationDetailDataContract
{
public string Planet { get; set; }
public bool? IsCapital { get; set; }
public int Population { get; set; }
}
internal class PlantDetailDataContract : LocationDetailDataContract
{
public int Population { get; set; }
public string System { get; set; }
}
internal class SystemDetailDataContract : LocationDetailDataContract
{
public string Sector { get; set; }
}
internal class SectorDetailDataContract : LocationDetailDataContract
{
// For now nothing
}
#Ruhrpottpatriot, why all classe are inheriting from LocationDetailDataContract?
Doing this i believe you will have a buch of classes and tables but the data will remain desnormalized (ex: CityDetailDataContract will have the column Planet with repeated strings.
Are you allowed to do something like this from you original question?
internal class LocationDataContract
{
[Key]
public Guid Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public DbGeography Coordinates { get; set; }
public LocationDetailsDataContract Details { get; set; }
}
internal class LocationDetailsDataContract
{
[Key, ForeignKey("Location")]
public Guid Id { get; set; }
public Planet Planet { get; set; }
public System System { get; set; }
public Sector Sector { get; set; }
[Required]
public LocationDataContract Location { get; set; }
}
internal class Planet {
[Key]
public Guid Id { get; set; }
public string Name { get; set; }
public bool? IsCapital { get; set; }
public int Population { get; set; }
}
internal class System {
[Key]
public Guid Id { get; set; }
public string Name { get; set; }
}
internal class Sector {
[Key]
public Guid Id { get; set; }
public string Name { get; set; }
}
I am trying to make a wcf data service where i dont want to get acces to the database models but instead i want to use Data transfer objects. I have been reading a lot on the internet about how to accomplish this but i cant get a good answer for my problem. It is the first time for me doing something with wcf data services so i am a little inexperienced.
Oke here are my models that are linked to my database using Entity Framework
public class User
{
[Key]
public int UserId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
public string CountryCode { get; set; }
public string PhoneNumber { get; set; }
public ICollection<User> Contacts { get; set; }
public virtual Language Language { get; set; }
public User()
{
Contacts = new List<User>();
}
}
public class Message
{
[Key]
public int MessageId { get; set; }
public DateTime SentDate { get; set; }
public virtual User Sender { get; set; }
public virtual User Receiver { get; set; }
public string Content { get; set; }
public string OriginalCultureInfoEnglishName { get; set; }
public string ForeignCultureInfoEnglishName { get; set; }
}
public class Language
{
[Key]
public int LanguageId { get; set; }
public string CultureInfoEnglishName { get; set; }
}
Now i made a Service.svc which has my DatabaseContext so it can directly acces my database models. What i want to achieve is that instead of directly getting the database models i would like to get the DTO models when i query against my service.
A Example of how my dto's would look like
public class UserDTO
{
public int UserId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
public string Country { get; set; }
public string PhoneNumber { get; set; }
public ICollection<ContactDTO> Contacts { get; set; }
public virtual LanguageDTO Language { get; set; }
public UserModel()
{
Contacts = new List<ContactDTO>();
}
}
public class ContactDTO
{
public int UserId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
public string Country { get; set; }
public string PhoneNumber { get; set; }
public virtual LanguageDTO Language { get; set; }
}
public class LanguageDTO
{
public int LanguageId { get; set; }
public string CultureInfoEnglishName { get; set; }
}
public class MessageDTO
{
public int MessageId { get; set; }
public DateTime SentDate { get; set; }
public virtual ContactDTO Sender { get; set; }
public virtual ContactDTO Receiver { get; set; }
public string Content { get; set; }
public string OriginalCultureInfoEnglishName { get; set; }
public string ForeignCultureInfoEnglishName { get; set; }
}
Now is it possible to do it like this by making a different context that i can use in my service.svc or is there any other way to achieve the this?
for example i would like to get ContactDto by userid which is a user but with less properties because they are not relevant in the client application. I see this happening by a uri http://localhost:54895/Service.svc/ContactDto(1)
Hopefully anyone can clear this up for me because it is really frustrating :)
I'm not sure that what you're interested in is possible, exactly. You are looking to have multiple entity sets per type (aka MEST), and I don't know how well that's supported.
Beyond that point, and into a discussion around DTOs in general...
If you use custom providers, you can implement your own IDataServiceMetadataProvider and IDataServiceQueryProvider. When your service starts, you can make calls into the IDataServiceMetadataProvider to control what entities and properties are exposed or hidden -- including exposing properties that do not actually exist on your entity. The upshot is that you end up with a DTO without coding a DTO class. The exposed metadata is the DTO. This is a good resource for creating your own providers.
In your case, this isn't a 100% solution, because you can't selectively choose when a property is exposed and when it's not.
Hope this helps...
Pardon any misspeaking I may do. I am just learning asp.net c#, OOP, and MVC 4.
I am using the Annotator plugin on my site and I am trying to store and retrieve the results from a data base. When a new annotation is created it sends information like this to the controller.
{
"text":"asdas sd a dasd as dasd",
"ranges":
[{
"start":"/div/p[3]",
"startOffset":195,
"end":"/div/p[3]",
"endOffset":532
}],
"quote":"Some quote that was selected.",
"UserID":"1",
"ProjectDocID":"1"
}
Now, I hoped something like this would load all the data into a nice easy object.
// GET: /Annotation/Create
public ActionResult Create(Comment comment)
{
db.Comments.Add(comment);
db.SaveChanges();
return Json(comment);
}
The model I had looked like this (and I am change it however it needs to be changed).
public class Comment
{
[Key]
public int CommentID { get; set; }
public int ProjectDocID { get; set; }
public int UserID { get; set; }
public string text { get; set; }
public string Annotation { get; set; }
public string quote { get; set; }
public string start { get; set; }
public string end { get; set; }
public string startOffset { get; set; }
public string endOffset { get; set; }
public DateTime DateCreated { get; set; }
public virtual ICollection<CommentVote> CommentVote { get; set; }
public virtual ICollection<CommentReply> CommentReply { get; set; }
public ProjectDoc ProjectDoc { get; set; }
public virtual User User { get; set; }
}
What do I need to do to get the data from the server and map it to the model. I also need to be able to send it back in the format at the top so the plugin understands it when it asks for it from the Details action in the controller.
Not sure if this is the right way to do it or not, but it lets me store it in the database and that's all that matter for the moment. I updated my model as follows.
public class Comment
{
[Key]
public int CommentID { get; set; }
public int ProjectDocID { get; set; }
public int UserID { get; set; }
public string text { get; set; }
public string quote { get; set; }
public DateTime DateCreated { get; set; }
public virtual ICollection<CommentVote> CommentVote { get; set; }
public virtual ICollection<CommentReply> CommentReply { get; set; }
public ProjectDoc ProjectDoc { get; set; }
public virtual User User { get; set; }
public List<ranges> ranges { get; set; }
}
public class ranges {
public int ID { get; set; }
public string start { get; set; }
public string end { get; set; }
public string startOffset { get; set; }
public string endOffset { get; set; }
}
This matches the JSON object I am sending in to the controller with Ajax. Once it matches exactly the controller action above works.