How to add database views as part of IDatabaseInitializer - ef-code-first

I would like to map a POCO class to a database view. My goal is to create the view using a custom database Initializer (Implementing IDatabaseInitializer<T>)
Unless I'm mistaken, I must decorate the class that maps to the view with the [Table("MyViewName"] attribute. However when I do this Database.CreateIfNotExists() will create a table called MyViewName, before I get a chance to execute the SqlQuery command that creates the view.
I suspect I'm doing something out of order, but with only one method in the IDatabaseInitializer interface to work with, I can't see what it could be.

One possible solution is to simply let the CreateIfNotExists do it's thing, and then drop the newly created table and replace it with a view. Seems somewhat hackish but it does work.
if (context.Database.CreateIfNotExists())
{
context.Database.ExecuteSqlCommand(#"drop table MyCustomView");
context.Database.ExecuteSqlCommand(#"create view MyCustom View as ...");
}

Related

ADO.Net EF, Inheritance Table shows, but not the model

I have created a Entity named MediaItem which is Abstract and Game inherits form it. I create the database automatically and I get a table MediaItems and MediaItems_Game.
The issue is when I do the following in my ASP.Net Controller:
private Models.DBContainer dataModel = new DBContainer();
dataModel. ---> Intellisense shows me MediaItem but I can find no way to either navigate to or use MediaItems_Game, how can I solve this? i.e. How can I grab a list of 'Games' with some 'WHERE' constraints on another table (not pictured).
Any info is appreciated, thanks.
This is how inheritance in EF works. You have only single set of parent type. If you want to get just games you will use OfType method:
var games = dataModel.MediaItems.OfType<Game>().ToList();

How to return two types of objects in an ASP.net MVC view

I have say class/ojbect one which I am returning as details. But then there is a second class that is related to the first that I want to list (and have an option to look at the details). How do I get return both of those?
Example is like in an item as the main piece but there may be details or other items that are related to the main item. I will select them with a linq query but then how do I return them to the same view?
Do I need to have some sort of partial or other form to display the second object type?
I don't see where returning the view I can return both.
My thought for right now is to create a new class that contains both of the object types but I know there has to be a better way.
My thought for right now is to create a new class that contains both of the object types but I know there has to be a better way.
That is the right way. Create a ViewModel class that contains all the data that view needs and pass it to view.
You can either pass it to View through ViewState or ViewBag (depending on which MVC version you are using).
for the first object "main object" return it as the model of this view and for the details
put them into ViewState and cast them back within the view

NHProf generates 'this statement executed from the view' warning when I pass a ViewModel object to my ASP.NET MVC View page

I just noticed that on one page of my site, where I pass a ViewModel to my View page, NHProf is giving the following warning:
This statement executed from the view, which can result in bad performance and/or brittle behaviour.
It then links to this page: http://nhprof.com/Learn/Alerts/QueriesFromViews
My ViewModel consists of just 2 properties:
public IEnumerable<Photo> Photos { get; set; }
public Photo SelectedPhoto { get; set; }
I assign the photos to this ViewModel within my Controller as follows:
PhotoViewModel myViewModel = new PhotoViewModel();
myViewModel.Photos = entity.Photos;
My View obviously inherits this type, and aside from outputting a header (which makes use of the SelectedPhoto object), it just loops through each of the Photos rendering some content for each of them.
NHProf shows the 'problem' query as being where it retrieves the collection of Photos that I'm looping through in my view, though I'm not explicitly telling it to go off and get those records from within my view - I've passed those records within the Photos property of my ViewModel.
I have other pages where I don't need to pass a ViewModel and I simply pass IEnumerable<Photo> to the View, and then render the markup exactly the same as I do in the problem view, and NHProf gives no warnings (as there shouldn't be) in that scenario.
I'm thinking maybe it's related to Lazy Loading, and because my collection is part of a ViewModel, when I go to loop through the Photos property within the ViewModel type, it goes to get those records at that point?
Does anyone have any idea what is happening here? The site functions perfectly, but NHProf just sees that it's doing something from where it shouldn't be doing it?!
You haven't shown how your Photos collection is being populated, but I assume it's as simple as viewModel.Photos = entity.Photos. If that's correct (or something similar), then you're just assigning the lazy-loaded entity collection to your view model.
There are several ways to tackle this, but they're all essentially the same: you need to trigger the loading of your collection before you populate your view model. The easiest way to do it is to just stick a .ToArray() or equivalent onto the collection you're assigning; that'll force a fetch.
You are right. It is related to Lazy loading. Try to load Photos eagerly. And check their relations. Maybe they have some with eager loading, you don't need, or you are trying to use associated entity in your view.

How to persist a change in a DBML

I have a table of users called Users
And a view called UsersActive that filters out deactivated users.
When I create my DBML, I drag the Users table in, then I change the property on the table to point to UsersActive.
This works well, until the DBML gets re-created.
Does anyone know how to fix this?
I've tried overriding the
[Table(Name="dbo.Users")]
attribute in a partial class but get the error:
Duplicate 'Table' attribute
Does anyone know how to go about this?
Thanks in advance!
-Ev
You should just be able to add the View to the DBML, just like a table...yes?
Update: No, it will probably not maintain the relationships -- views don't have relationships.
It sounds like your goal is to query active users in a simple way, without having to specify the criterion in each query?
What you might do then is to have a repository class with a method of GetUsers(). That method does the Linq query and ensures that the active criterion is always there.
Perhaps the method would have a signature of Respository.GetUsers(bool includeDeativated = false). Calling GetUsers() without arguments will not return deactivated, but you can override it if desired.

DataGrid crash on CompositeCollection Edit

I have a DataGrid.
It's ItemsSource is bound to the ModelView's CompositeCollection through the ViewModel.
The CompositeCollection consists of 2 ObservableCollections.
The display on the grid is fine. I am able to see the collection.
However, when I try to edit one of the rows, I get a crash (NotSupportedException) of:
"'EditItem' is not allowed for this view"
How do I make the rows editable? I need to be able to edit the ModelViews representing each row in the Grid.
Here is the CompositeCollection Property code that I use to bind to the itemssource:
this isn't the exact code since I am not allowed to post the exact code but it is the same logic on how I make the collection
public CompositeCollection ModelViewsCollection
{
get
{
CollectionContainer modelViewContainer;
CompositeCollection modelViewCollection = new CompositeCollection();
modelViewContainer= new CollectionContainer();
modelViewContainer.Collection= this.ModelViewCollection;
modelViewCollection .Add(modelViewContainer);
modelViewContainer= new CollectionContainer();
modelViewContainer.Collection= this.ModelViewCollection2;
modelViewCollection .Add(modelViewContainer);
return modelViewCollection;
}
}
CompositeCollection does not implement IEditableCollectionView which is used by the datagrid to edit.
I have had the same issues, and ended up doing my own fake composite collection on the view model, similiar to what you have, if all you are putting in your collection is two observable collections, its not to hard to track the changes listening to collection changed on both of them. and make your viewmodels collection consist of both of them
You could even do the dirty hack that i did, of rebuilding the ObservableCollection that the grid binds to every time one of the collections change (not elegant i know, but ill go back and optimise when i get time.. i.e. never) With a linq query this stuff is really easy.
Otherwise maybe you could derive from CompositeCollection and try and add the IEditableCollectionView, if you get that working be sure to let me know.
here is the same question on the datagrid forum

Resources