Image database organization - asp.net-mvc

I am curious as to how I should organize image storage in my application. They will be stored on disk somewhere, with the path / url stored in the database, but my application has become complex and image organization is leaving me baffled. The technology I am using is ASP.NET MVC 3 + EF 4.1 Code First (which is proving to be difficult with complex relationships).
This is a family based application, so there is a Family table, Member table, and a FamilyMember table to link to two. There is also a FamilyEvent, and MemberEvent table to track events in the family or member's life.
Use cases
A Member can upload multiple profile pictures (possibly to be put in a "profile" album?)
A Member can upload "family" photos, to be attached to the Family object, and put into some type of album for the family.
A Member can add a member event, and attach multiple images to the members event.
A Member can add a family event, and attach multiple images to the family's event.
These are the base use cases.
My thoughts
Base "Picture" table with id, description, and maybe the user id of the uploader.
MemberProfilePicture table with id, pictureId, memberId, etc...
MemberEventPicture table with id, pictureId, [member id?], membereventid, etc...
FamilyEventPicture table with id, pictureId, [familyId ?], familyeventid, etc...
This would allow a family or member to essentially "link" a Picture later to another profile pic / member event / or family event.
My question
Is this correct, or am I over-complicating this? I don't see any other way other than multiple tables to represent images for different things, which all refer to the base Picture table. Can anyone give any suggestions as to how I can improve this model? While I understand there may be many definitions to correct, I'm looking for solutions as far as how to organize the imaging aspect of my application, or improvements on what I have already.

Your using EF Code First so let's talk code not tables. You can realize your use cases by having only one Picture class and associate many Pictures with Member, Family and so on.
Taking this code
public class Family
{
public int Id { get; set; }
public virtual ICollection<Picture> Pictures { get; set; }
public virtual ICollection<Member> Members { get; set; }
}
public class Member
{
public int Id { get; set; }
public virtual ICollection<Picture> Pictures { get; set; }
}
public class Picture
{
public int Id { get; set; }
public String Location { get; set; }
}
Will generate 3 Tables, Families, Members, Pictures with the Pictures table having two foreign keys Family_Id and Member_Id. This model allows to associated a single picture with Member, Family or both.
From a scalability point of view I would avoid to store the image binary in the database and using an ORM to access the binary. Better ideas are to store the picture in the file system or a "specialized" server like MongoDBs GridFS.

What I would do is have three tables.
The 'picture' table which stores a unique id for each picture and the location.
The 'profile' table which has your dtails about the profile.
A third 'linking' table composed of pictureId and profileId
If I want to link picture A to profile X I just add in "A,X" to the linking table. Same thing for events or whatever. If there's going to be a many-to-many relationship this is the cleanest way to go (I'm assuming that the same picture can be in multiple profiles).
Hope I understood your problem correctly.

Related

Entity Framework - how to implement Tags (for Articles / Pages)

I'm writing a EF based website which will have many Articles (with id, author, date, title etc attributes) each of which is a member of a Category (10 possible categories each with id, title, associated icon etc)
Each article can also have several "tags". Like the question-tags that apply to SO questions.
For example Article ID 1 has:
Title: "10 most popular baby names of 2016", Author: "Jo Bloggs", Date: 2017-02-01, etc
CategoryID: 2 (foreign key to Category table where ID 2 is the "Year In Review" category)
(This is the part I'm unclear about) Tags: "Lists", "Top 10s", "Parenting", "2016", "Trends", "Babies", "Names"
Article ID 2 ("50 life hacks I discovered this year")
has its own Title, Author etc, also a FK to Category ID 2
(This is the part I'm unclear about) Tags: "2016", "Lists", "Life Hacks", "Self improvement"
From the above there are 9 'distinct' tags of which 2016 and Lists apply to both articles and the others appear once each.
With a large number of articles there are an increasingly large number of tags.
Is this just a case of a many-to-many relationship of Article to Tag or is there some more natural/idiomatic way to represent that using EF?
The main things I want to do are:
On an article page, show the tags that apply to that article (like the Stack Overflow tags that apply to a question when you view it).
Show a 'tag cloud' or list of tags with the number of articles that have been tagged as that. e.g. Lists (2) , Trends (1)
Potentially when creating an Article, be able to create a new Tag to go with it if the tag doesn't already exist (although if this is too difficult I can create the tag upfront instead).
I don't need to:
query the articles to find articles where tag = THIS and not THAT or any similar logic
preserve the ordering of the tags (I will sort them in the view/controller logic so it doesn't matter in what order they are stored)
What I need to know:
How should I model the tags in the database (should there be a Tag table and a ArticleTag table (ArticleID, TagID) or something else?)
What would I need to model using EF to represent the article--tag relationship efficiently?
My background is database so I understand about FKs and link tables etc, but am struggling on the EF side.
Note about my requirements: This is for a website I am creating for myself, so I already know the requirements. I won't have a situation where "the user" asks to be able to keep the ordering of the tags, for example.
You can add 2 Tables, Tag and TagRelation, Tag is responsible for saving TagNames such as #Test #AnotherTest, make sure there is no way to insert same tagName.
In TagRelation you should keep the TagId (Fk of Tag table) and Guid (Fk of Article, Page and you name it).
In this architecture every table needing Tag, must have a field with Guid type(uniqueidentifier in SQL data type) when you searching for ex. article you simply set inner join with TagRelation on Guid fields
public class Tag
{
public long Id { get; set; }
public string TagName { get; set; }
}
public class TagRelation
{
public long Id { get; set; }
public long TagId { get; set; }
public Guid FkUniqueGuid { get; set; }
}
public class Article
{
public long Id { get; set; }
public Guid UniqueGuid { get; set; }
//And another fields
}

Changing relationships between tables to simplify data access in MVC3

Asp.net MVC3 app with Entity framework. Lets say I have 3 tables; Article, Category and Author.
I create relations between
Category.CategoryId -> Article.CategoryId and Author.AuthorId -> Article.AuthorId
Using code first navigation properties
public virtual Category Category { get; set; }
public virtual Author Author { get; set; }
That means that when I view a list of the articles I have to :
return View(db.Article
.Include(c=>c.Category)
.Include(a=>a.Author)
.ToList());
In order to have access to the names of categories and authors and not just their id’s
How much would it hurt to break this classic schema and not create relationships between these tables? Then I could just return SelectLists from Author and Category Tables in a ViewModel and populate the Category and Author fields in my Article table directly with the corresponding names not the id’s and also preserve data integrity.
My query would be simplified to just:
return View(db.Article.ToList());
I suppose I will have to create indexes for those fields to speed up searches.
Is this being done somewhere or is it completely wrong?
Does it have better or worse performance?
#Panos, your original approach is correct, deleting foreign keys would be a mistake. With the includes you avoid the lazy loading in this scenario and you have a good performance.
public virtual Category Category { get; set; }
public virtual Author Author { get; set; }
you defined category and Author as virtual and it means these object wont load without an Include command in your query. you man use a select list in your grid without removing these relations, because these relations doesn't have any real load without Include command in your query.
but be aware of using .ToList() this will load all records of your query and later it may become a large amount of data.

How to delete all many-to-many relations without loading related entities in Entity Framework?

I have db scheme where Product table have many to many relation to Color table. I'm using EF and create POCO objects:
public class Product
{
public Guid Id {get;set;}
public ICollection<Color> Colors {get;set;}
}
public class Color
{
public Guid Id {get;set;}
public ICollection<Product> Products {get;set;}
}
In many situations it is necessary to delete all colors related to product and set new colors. So i want to delete all many to many relations whitout exactly knowing id of related colors. Is it possible to delete them without additional queries to db? I know i can just write stored procedure which will delete all relation with colors for specified product, but it will be better to find general approach through entity framework.
If you don't know keys of colors you cannot delete them without loading them first - EF deletes records one by one so it needs to know which record to delete.
The straight forward option is executing SQL DELETE directly:
dbContext.Database
.ExecuteSqlCommand("DELETE FROM dbo.ProductColors WHERE ProductId = #Id", product.Id);

Benefits of not passing entities to view

I usually see people telling that you should not pass entities to your View. They say you should use a DTO/VO/ViewModel/AnyOtherThingYouWant instead, as using an entity would increase the coupling.
Ignoring the moments where I do need some extra logic (or I don't need all the properties), I fail to see any benefits in doing this. For example, consider the following class:
public class Contact {
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
}
I see lots of code that creates another class, like this:
public class ContactDTO {
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
}
use it in the View and then do this:
someMapper.Map(contactDto).To<Contact>();
I can't see how better this is than simply using the Contact class, as your View would be coupled to a class that is coupled to the entity's class. So, every change in one should be replicated into the other. From my point of view, the 'middle' object is there just to add complexity, but not real value.
I know that there's no 'one size fits all' solution (as sometimes, using the middle object would make sense), but do we really need adding code like this? What are the real benefits?
Think of it this way: a view is a projection of your domain. It's a specific representation of your business model. So you need to use a view model which will represent this projection. It could be a subset of the domain model but it could also be an aggregation of multiple domain models if the view requires it. The example you provided is just a specific case where there is a 1:1 mapping between the domain model and the view model because of the requirements of this specific view. But that's only one specific view. I suppose that your application has many views and different representations of your domain entities.
There are many view specific things that make your domain models unsuitable and thus the need of view models. For example validation. A given domain model property could be required in some view and not required on another view (think of Id property in Create/Update views). If you don't use a view model but have your Create controller action directly take the domain model you will have a problem if your domain model Id property is decorated with the Required attribute.
There are many other examples. If I had one advice to give you when developing an ASP.NET MVC application it would be this: always define specific view models for your views and never pass/take domain models to/from views and this stands true even in cases where you have a 1:1 mapping between your domain model and the view model.
The cited approach is a kind of purism. If you do not need to transform (reduce, merge, whatever) your domain objects and they are directly usable in your view as they are, use them - you can introduce DTO via refactoring later, when necessary.
So you have to take into consideration what Darin Dimitrov said but keep in mind that DTOs and similar are here to make your work easier. I recall one project I worked on - more than 90% of DTOs were ono-to-one copies of the domain objects - this is totally useless and only adds to the maintenance cost.

Good idea to resolve User roles in the application layer?

The reason I need a role-based system:
Restrict access to pages.
Restrict access to certain features on pages.
Check/validation inside service layer.
So I'm guessing, I can just create an enum and if I need a new role, just add it to the app code (the app would change anyways so requires a recompile).
So right now I have
public class User
{
/* .. */
public virtual ICollection<UserRole> Roles {get; set;}
}
public enum UserRoleType
{
Administrator,
User
}
public class UserRole
{
public int UserRoleId { get; set; }
public int RoleTypeValue { get; set; }
public UserRoleType RoleType
{
get { return (UserRoleType)RoleTypeValue; }
set { RoleTypeValue = (int)value; }
}
public virtual User User { get; set; }
}
This is a 1 to many. The pros I see for this is that instead of a many-many, there is a 1-many and joins are less. The application already knows what the role is based on what the int resolves the enum to.
Are there any flaws in the way Im doing this? Is there anything you have met in your experience that would require me to store the actual values in the database?
To be clear, you are suggesting that you don't need an actual lookup table in the database for Roles? Instead, they just have an int that is not a foreign key to anything--it is simply a representation of the enum in the application?
It's impossible to answer definitively without knowing all the details of your application. That disclaimer aside, I see nothing inherently problematic about it. It would certainly work fine for some systems.
Possible downsides:
There is no source of valid values enforced on the database side via referential integrity. What is to stop someone from entering "12452" for the RoleId in the database column? There are other ways around this like using check constraints, but they are not necessarily easier to maintain than a lookup table.
There is no way to effectively query the user/roles tables and have a human-readable representation of roles without knowing what the RoleIds represent (you will have to have the enum in front of you to make sense of the query result).
If the database is used for other applications, the roles will need to be represented (and maintained) in that application as well.

Resources