LINQ many-to-many relationships: Solution? - c#

LINQ so far has been remarkably elegant, but to perform basic m2m queries it offers no solution I can imediately see.
What's worse is that while it works for any other table relationship, LINQ is not giving me an association in the class structure for my m2m table.
So I can do things like
artwork.artists.where(...)
//or
artist.Artworks.add(artwork)
but I can't do
artwork.artowrks_subjects.tagSubjects.where(...)
//or
tagSubject.artworks_subjects.add(artwork)
alt text http://img299.imageshack.us/img299/257/20090902122107.png
Is there a common pattern for solving this limitation?

the way I have gotten M2M working in LINQ2SQL:
drag the tables into the builder,
like you're showing in the question
remove the relationship between
artworks_subject and artwork
create a new relationship FROM
artworks_subject TO artwork
click on the new relationship to get
its properties
change the
cardinality from OneToMany to
OneToOne (because ManyToOne doesn't
exist)
open the Child Property
section and change the Name field to
make it singular (Artworks to
Artwork)
now the tagSubject entity will have a collection of artwork_subjects, and the artwork_subject will have a property of type artwork called Artwork. so you can now make a LINQ expression like
var x = dbcontext.tagSubjects.Single(s=>s.name=="Landscape").
Artwork_Subjects.
Select(as=>as.Artwork.Name);

Found the solution myself. For automated relationships to work, both tables need primary keys (oops). Notice artworks_subjects is missing the PK symbol.

This largely depends on what framework you are using. It sounds like you are using LINQ-to-SQL, which is very literal about tables to objects. With Entity Framework, there is inbuilt support for many-to-many, in particular for the trivial case you've listed (a linking table with no additional properties). EF will generally spot this pattern, and hide the link table from the conceptual model (I can't remember, but it might need a spanning PK over the two FK columns).
Of course, this then goes sour if you want to add columns to the link-table; so in some ways I'd be tempted to leave it "as is".
With regards the where etc - how do you mean? You can do joins over the association, and you should be able to use Any etc; do you have a concrete example of what you want to do?

Yes. Instead of many-to-many use two many-to-one relationships:
Subject -*----1- ArtworkSubjectParticipation -1----*- Artwork

Related

unwanted column in entityframework database

I am working on an MVC project in Visual Studio Ultimate 2013 and I have some unwanted columns in some of my tables and I cannot really understand why is it so.
In table Categories there is the column Template_TemplateId which is probably because in the Template entity class there is a ICollection<Category> property.
I want a Template to have many categories, however a one category can be repeatedly used by many Templates so I guess the Template_TemplateId column is something I don't want there.
Can someone explain, why is this so, and what should be a right approach to have the model the way I want it?
Thank you.
Model First:
Be default, EntityFramework creates one-to-many type relationships. When you create those, you need a foreign key in the "one" side of the relationship.
This is the "Template_TemplateID" field. It is the foreign key into the "Templates" category. However, you said you wanted a many-to-many relationship, so you are absolutely right; that field is useless!
You need to specify a cardinality of "*" on both ends of the relationship, then the model will create an intermediate table allowing the many-to-many relationship. The foreign key should go away at this point.
Code First:
Same problem, but the solution is to make a collection of "Template" in categories and and a collection of "Category" in templates, thus creating the many-to-many relationship.
If you want a many-to-many relationship between Templates and Categories create two collections, on on each class - on Template, create a ICollection and on Category, create ICollection.

EF Fluent Mapping - map a collection field from another table

This may already have been asked somewhere, but I can't find a question exactly matching what I'm trying to do.
At the database level, I have TableB which has only two fields - a foreign key to TableA and a nvarchar(max) Code field. The relationship from TableA to TableB is one-to-many.
At the EF level, I would like to skip mapping TableB at all. TableA would look like this:
public class TableA
{
public ICollection<string> BCodes {get; set;}
}
I would like BCodes to be populated from the Code field of all of the related TableB entities. I know I could accomplish this using views and other hacks on the database, but that destroys the separation of concerns. Is this possible using EF, or do I have to map a TableB entity with just the one string property?
Update
I should clarify that this can be a read-only collection for my specific case. Other people who stumble across this question may have different needs, so if you have ideas of a read/write way to implement it, that would be great too.
At least up to EF 6.1, it's not possible to define primitive type collections (for example a collection of strings). It must be done indirectly.
The best approach I've ever seen is this SO answer.
Alternatively you could use NHibernate, that support this functionality. For example, you can see this SO question.

Am I doing many to many incorrectly when using fluent nhibernate?

I have two main entities (db tables)
Project
Application
I have a bridge tabled called ProjectApplication with 3 col (Id, ProjectId, ApplicationId)
A project can have many applications.
An application can below to many different project
Your basic many to many mapping
Currently this is what i have setup in my fluent nhibernate mapping files
public class ProjectMap
{
HasMany(x => x.ProjectApplications)
.AsBag().Inverse().Cascade.AllDeleteOrphan().Fetch.Select().BatchSize(80);
}
public class ApplicationMap
{
HasMany(x => x.ProjectsApplications)
.AsBag().Inverse().Fetch.Select().BatchSize(50);
}
Is there any downside to this as i see there is a HasManyToMany syntax so I am not sure if it makes a difference in terms of the Queries that are generated or performance, etc
Please advise
In general there are two approaches, as you've correctly mentioned:
explicit mapping of the pairing object, resulting in one-to-many and many-to-one
implicit mapping without any knowledge of the underlying table using many-to-many
I (my personal statement) would avoid many-to-many in almost any scenario (while in some very rare, really admin object scenario could be used).
Here are some of my tries, to explain that:
How to create NHibernate HasManyToMany relation
many-to-many with extra columns nhibernate
Nhibernate: How to represent Many-To-Many relationships with One-to-Many relationships?
To add more here, I would firstly mention, that with many-to-many we are loosing the pairing object from the model. Forever. So, once our customer will come and ask: please, make one of my relations Main, or introduce the Sorting - we simply cannot. The relation is as it is. No way how to extend it.
And secondly, and most likely - very likely: our customer will come and ask: Could you create a filter for me, selecting only Projects which are related to Application having some setting set to true AND ...
And that would be a bit challenging in many-to-many case.
The scenario with explicit pairing object brings more overhead with that third Entity. But could be converted into Subqueries
There are some examples of the Subquery power:
Query on HasMany reference
Is it possible to query all objects that have one or more possible children using NHibernate?
Well, that is my point of view. Not saying it is correct. But my experience shows, that with explicit pair object mapping we are ready for extensions as well as for complex queries.

Entity Framework: subset entity of larger entity

Sooo basically I have a table called Comment. On that table I have three fields,
ID
Title
Text
I've created an Entity object for the table already and it maps all three fields, but what I want now is another Entity called CommentHeader that will map only ID and Title. I want to only load the titles of all the comments and not the text for speed reasons. So what's the best way for going about this?
I'm not looking for a Select statement with a var object. I can figure that one out on my own and I really don't like that solution because I'd much rather abstract it behind an Entity object.
I've tried the obvious solution, which was to just copy the original Entity object and delete Text from it. That resulted in an error because only one Entity can map to one table without conditions. It sounds to me like I have no choice but to use a Select statement. I just wanted to make sure before I did something stupid.
(By the way this example only has three fields for simplicity's sake. Assume that the header could have considerably more fields in it. This is the primary reason I don't want to just use a select with a var object, because it's not just one field but could be a whole bunch of fields).
The easiest way probably would be to create a view ("CommentHeaders") in the database that only selects ID and title from the Comment table. Then update your model and add the view, which will create a new entity based on those columns.

Inheritance of database tables in VS

I want to create Table-Per-Type database table inheritance.
Simply base table RowElement will have 2 children tables. First child table Lyrics will inherit all parents RowElement's columns and will just add one more column. Second child table ChordUse will only many-to-one relationship to table Chord.
This is how my database schema looks like:
alt text http://www.freeimagehosting.net/uploads/ae4d8bd348.jpg
The problem is that when I let the VS create E/R diagram for me it creates this:
alt text http://www.freeimagehosting.net/uploads/774b194451.jpg
So it creates an 1-to-1-0 entity relationship instead of inheritance. I can't get VS to create inheritance relationship mapped correctly to database. Please help me.
After generating E/R diagram from my database I would like to have something like:
alt text http://www.freeimagehosting.net/uploads/e532f09b8a.jpg
Where RowElement is abstract class. Thank you for any help.
The EF designer (for good reasons, IMHO -- inheritance is overused in OR models) will never infer inheritance. You need to set it up yourself. You are asking for "table per type" inheritance. Follow the walkthrough with the demo model. When you've got that working, you'll be ready to do it with your real model.

Categories