Linq to SQL Entity Splitting - asp.net-mvc

I've recently started playing around with the ASP.NET MVC NerdDinner sample, and as part of that you get to play around with Linq to SQL classes. This looks cool, so I decided to break away (perhaps a tad prematurely!) and try and create my own MVC application, but this time modelling my own simple database with Linq to SQL.
The problem I'm having is this. Consider these tables:
Car
Person
Passengers
The table CarPassengers is a mapping table between Car and Person (it has two columns: CarId, PersonId).
In Linq to SQL, I get a class for every table. But, what I really want is a class for Car that has the property CarPassengers, with each child being a Person, rather than the actual FK's (it's ok for selecting results, but to update Car with new Person objects, I have to first construct them - I can't just add an EntitySet of CarPassengers without first instantiating the child Person objects, I think).
I've been looking around and I've seen that the ADO.NET Entity Framework will allow me to achieve this using Entity Splitting, but I wondered if there's an easy way to accomplish the same thing in Linq to SQL, and if not, what the affects are in terms of integrating the .NET EF with my MVC app.
Any advice, comments, tips would be much appreciated.
Thank you!

If you define the FKs prior to adding them to the designer surface you will get the EntitySets added to the class in a manner close to what you expect. CarPassengers will exist but it will be an EntitySet of CarPassenger objects, not Persons. Those objects, however, will have an associated Person EntityRef. This will allow you to find the passengers in the car.
var car = db.Car.Where( c => c.CarId == id );
var passengers = db.Car.CarPassengers.Select( cp => cp.Person );
Adding new passengers works as well, but also involves another step.
var car = db.Car.Where( c => c.CarId == id );
var person = new Person { ... };
car.CarPassengers.Add( new CarPassenger { Person = person } );
If you don't have the FK relationships defined ahead of time, you can always add the associations manually in the designer. MSDN has a HowTo article on this topic.

Related

How to get data from 2 entities in MVC ?

I am developing MVC application and using razor syntax. I have used model first method.
I have two entities, Customer and Lead. Lead is inherited from Customer.
When IsActive property is true then Customer treated as a Lead, otherwise it will be a customer.
Please check edmx file image.
Now, In regular entities we just deal with single entity and single table.
In this case how can I handle , Save and Load process. beacuse I have to store and load the record from 2 tables of DB.
Is Regular Index View will work here ?
When using inheritance in the Entity Framework you will have a single DbSet on your DbContext that exposes your hierarchy. In your database you have several options for configuring your table structure. For example you can use:
Table per Hierarchy
Table per Type
Table per Concrete type
(See this blog for a nice explanation: Inheritance in the Entity Framework.
In your queries however, you don't have to think about this. Your queries will have the following structure:
var leads = from l in dbcontext.Leads.OfType<Customer>()
select l;
The OfType() filters your collection to a subtype in your hierarchy. If you skip the OfType you will get both customers and leads in your resulting query.

Model design in ASP.NET MVC

I am constanstly having problems with model design in MVC. Mostly all of my projects require some entities that are to be created, edited and deleted. Most of these entities have some common properties like creation date, modified date, author, modified by and in some cases even more descriptive properties are common. Because of that I have one single DB table to store them. For instance, Documents table and we store Invoices, Quotations and other business documents in it. I am using Entity Framework v4 for ORM, where we eventually end up with the Document entity.
How do I modify this entity or do I create a separate DocumentViewModel class for it to support multiple document types with common properties (so some form of inheritance or interface implementation should be implemented)? Besides identifying different document types I also need to have some types to have different Data Annotation rules (attributes).
For instance, Document table has PayDate column. Document type Invoice requires PayDate to be provided but document type Quotation does not.
This is the one single problem I am facing over and over with MVC and so far I've been handling it different every time but cannot decide how to properly handle it to achieve the maximum application maintainability and ease of development.
Have you considered making Documents entity abstract?
From the DB side, you will have Documents table containing just the fields shared by all Invoices/Quoations/etc. This field will have an IDENTITY PK - e.g DocId.
In the other tables, additional meta-data specific to that document can be stored, and the PK is a (non-IDENTITY) field DocId, which is also a FK to the Documents table.
On the EF side, Documents becomes an abstract entity, and the other entities inherit from this entity. This allows a nice OO paradigm to exist, and makes your code more robust.
We are currently using this scheme (EF4/SQL Server).
Your scenario sounds very similar to ours - consider using Abstract Classes.
EDIT
Thought i'd add a bit more info to how i've actually implemented this scenario, to put you on the right track.
As the comments to your Q state, we have little knowledge of your domain, therefore it's hard to make informed opinions. Personally, i chose to make my entity abstract, because certain functionality required a "mixed-bag" of items to be returned in one hit. There are other ways to do this of course (such as a stored procedure), but this allows a nice fluent interface between my UI (which is MVC by the way) and my service layer.
Works like this - here's how i get a single Post:
// var is strongly-typed to a "Post"
var somePost = repository.FindSingle(10);
Here's how i get a mixed-bag of Posts:
// var is strongly-typed to a "ICollection<Post>".
// "Title" is a property on my "Post" abstract POCO
var mixedBagOfPosts = repository.FindAll<Post>(p => p.Title = "Some Title");
Here's how i get a collection of "Reviews" (child of Post):
// var is strongly-typed to a "ICollection<Review>"
// "Rating" is a property on my "Review" POCO (derived from Post)
var reviews = repository.FindAll<Review>(r => r.Rating == 5.00);
The kicker is my repository is implemented with generics, and the type parameter ensures type-safety:
ICollection<T> FindAll<T>(Expression<Func<T,bool>> predicate) where T : Post
And it's implemented like this:
return myContext.Posts.OfType<T>.Where(predicate).ToList();
The OfType causes an inner join to the T (which is the child table), so only those records are returned.
Of course, i also have a service layer mediating between my UI and repository, but this should get you on the right track.
Also, you don't have to go with the whole Expression-predicate thing, i like this because it minimizes the number of methods on my interface, and gives full querying power to my controllers, whilst ensuring the queries are deferred to the point of the service layer, but not further.
If you don't like this, you could of course have regular parameters (string title, etc).
As i said, this architecture suited my domain requirements, so it may not necessarily suit yours, but hopefully it gives you some insight.
You can put a table in your EF model many times and just rename them to the entities you need. Just delete the columns you dont need from those.
For example, put in a Documents entity... now rename it to Invoice. Now add another one, and name it Quotation... on the Quotation, click on PayDate and hit the delete key. You can customize these all you want! You can do the same with other ORMs, just takes a little more work. With NHibernate you would manually create the Models, then map them to the same table, but only map what you need.

Eager Loading with Entity Framework and Asp .net mvc (From a rails background)

I have a few tables that reference the same table. For example:
Person has an address.
Business has an address.
When using the models I would like to do this in the controller:
person.Address.Zip
business.Address.Zip
I'm coming from a rails background where I can just declare a relationship and have all the above functionality. Force loading of the address when I get the object (person or business).
I'm new to entity framework, and I'm struggling with how to achieve that functionality. I can't include the table in both models (person and business). If I use repository pattern and add the objects to a partial for the class, then I'm using lazy loading.
Am I looking at this wrong? Any suggestions for patterns I could use?
If your using Entity Framework 4.0 with Visual Studio 2010 lazy loading is automatic.
If your using Entity Framework 1.0 your life just got harder...
To eager load with EF1 you have to use the Include() method on your ObjectQuery and specify which navigation properties ( address ). For example:
ModelContainer.Persons.Where(#p => #p.Id == 39 ).Include("Address")
For "lazy" loading you have to manually load all of the FK associations manually. For example:
var myPeople = ModelContainer.Persons.Where(#p => #p.Id == 39
if( !myPeople.Address.IsLoaded() )
myPeople.Address.Load()
Another option is to modify how EF1 generates your model types and include lazy loading out of gates.
http://code.msdn.microsoft.com/EFLazyLoading
Previously, I was creating an ADO.NET Entity Data Model for each controller.
Now I've created one Data Model for all tables (it's not a monstrous db). That way I can include the tables when I query for eager loading.
If anyone has a better suggestion. Let me know. If anyone knows the correct behavior with a large database, please comment. Would you want one large edmx file to represent the database?
Ideally you should be able to traverse the object model to get most of the data you need, starting with a reference to the current user object.

What am I missing with my Entity Framework?

I have asp.net membership and I use the built in Create user method since it is convenient now after this depending on the user I want to add 2 more fields to the aspnet_UserTable.
In my aspnet_user Table I have like this
// All Standard Fields that come with this table
ClubID<nullable)
ClubName <nullable)
I have a table that relates this
Club Table
ClubID<PK>
ClubName
So this relationship forms that one club can have many users. But one user can only have 1 club.
So now I been trying to figure out how to add the ClubID to the aspnet Usertable since it does not show up in the Entity Framework Diagram since it does not show FK.
// Note in this case I am just using EF made to create but in reality I will use the Membership.Create.
aspnet_Users test = aspnet_Users.Createaspnet_Users(Guid.NewGuid(), Guid.NewGuid(), "myTest5", "mytest5", false, DateTime.Now);
test.Club = Club.CreateClub("One224", "Two224");
test.ClubName = "go";
MyEntities.AddToaspnet_Users(test);
MyrEntities.SaveChanges();
So what I have works but it just makes no sense and I hope there is a better way. Like I try to create the club and then stick it in the test.club.
This add's the ClubID primary key but does not add the clubName.
So then I have to add the club name separately. Like why? Is there not a better way?
I also prefer linq method syntax so if it is needed and you know this syntax can you please write it in that.
I would recommend a few things.
One: Strongly consider not adding columns to the aspnet_* tables. If you ever want to change your authentication method down the road you'll be stuck lugging those tables around with you even though you won't need them anymore. Also, there may be a new, better version of the membership provider one day that you won't be able to upgrade because you have customized the membership schema.
Two: Instead, why not create a new table called User (or something of your liking) that has your own primary key but links back to the ASP.NET Membership unique key (the guid).
Your table might look like
User
UserId (PK)
AuthenticationUserId (FK back to aspnet_User table)
ClubId (FK back to your club table)
Three: I don't understand why you've repeated ClubName both in your user table and in your Club table. You really only need to define the ClubName once, right? Keep your Club table how it is but remove the ClubName column from the user table.
Your code above for associating the club with the user is correct and works because that's how the Entity Framework works. You're associating entities with each other and are abstracted from some of the relational aspects of your data schema. It's a little strange to get used to it first but it does work.

NHibernate + ASP.Net MVC - how to order data in strongly typed manned according to user selected field

I'm presenting data for users in a grid (ExtJS) with remote sorting and paging. Let's say I have a grid with some Orders. Order entity looks like Order{OrderNumber, Customer, Date, Address{Street, City, PostCode}}. Customer is mapped by NH as relation, Address is mapped as component. Data presented in the grid are flattened to columns named like this: OrderNumber, Customer.Number, Customer.Name, Date, Address.Street, Address.City, Address.PostCode.
User selects a column which he'd like to sort by and the grid sends the field name to server. Now on server side I need to restore backwards what entity property belongs to grid field name and decide if it's just component or if it's relation and build Criteria with CreateAlias + AddOrder etc. This logic is full of code like:
if (gridField=="Customer.Name"){
cri = cri.createAlias("Customer", "customerAlias");
cri.AddOrder(Order.Asc("customerAlias.Name"));
}
This is much simplified, but it neccesarily looks like this at the moment. I'm looking for some generic smarter solution. Any thoughts? The problem I'm facing now is that I can have a convention for transforming entity properties (including nested components and relations), but than I need to have a method how to determine if the field is mapped like component or relation. This would be quite heavy....
It would be quite heavy. I don't see a simple solution, but if you are planning on re-using this a lot, or need something very robust, you could build a system based on reflection.
Another possibility would be to use some T4 templates, but that would only help the 'string' issue, not the association issue.
How about:
cri = cri.CreateAlias( "Customer", "CustomerAlias" );
string sortProperty = gridField.Replace("Customer.", "CustomerAlias.");
cri.AddOrder( Order.Asc(sortProperty) );

Resources