简体   繁体   中英

C# Entity Framework Database First - use only some fields

I am creating a site using EF database-first with ASP.NET MVC (I follow all of this tutorial: https://www.asp.net/mvc/overview/getting-started/database-first-development/creating-the-web-application ) and everything is working ok.

The problem is that in the index view (the list of records) I want to remove one of the fields from the the entity. I don't just want it to be hidden in the views, but all together removed (the issue is that it holds a very big chunk of data, which make the loading of the list very slow).

On the "edit" view I do want to show and use all fields.

If I remove one field from the the entity, I get this error:

The entity type XXX is not part of the model for the current context.

on

 return View(db.XXX.ToList());

What can I do?

There are a couple of ways you can go about this. The issue, at hand, is the .ToList(). If you just do db.XXX, then you will obtain an Enumerable, which, until it is enumerated, is just a set of instructions to grab data from the DB. Once you call .ToList() it will actually go and grab the data from the DB, which is the step that is taking so long.

The best thing to do, in my opinion is define a ViewModel that contains all of the fields except the one with the large amount of data.

public class ViewModel
{ 
     public ViewModel(){}
     public int Id {get;set;}
     public string OtherData {get;set;}
}

Move the db.XXX outside of the View function as so:

var initialDBObject = db.XXX;

From there you can take your Enumerable (which is still just a set of instructions to access data from your DB) and Select it into your ViewModel object like so:

var viewModelObject = initialDBObject.Select(x=> new ViewModel
    {
        Id = x.Id;
        OtherData = x.OtherData;
        //do not add the large column of data to the ViewModel
    });

What is happening here (before calling ToList()) is you are modifying the query that linq generates behind the scenes to grab the data from table XXX (if you put a break-point on this line and hover over initialDBObject you will see the SQL that gets generated). Instead of just grabbing the data from table XXX, the query will grab the data and insert it into a ViewModel object (instead of the XXX object, as defined in your .edmx file) once you call ToList().

You can also

.Select(x=> new 
{
    Id, 
    OtherData
});

and create an anonymous object, but getting an anonymous object to work in a View is a little complicated.

Then you need to update the Index View page to use the ViewModel instead of the original DB object and you can pass it like:

View(viewModelObject.ToList()); 

Name the ViewModel something besides ViewModel, though. Like [DB Table Name]ViewModel or something similar.

If you have lots of rows in the DB it will still take a long time to load all of the data, in which case you need to look into Paging.

There is no problem with ToList(), on its own, the original issue was caused by the call to ToList() because it is at that point in the code that the program goes to the database and uses the linq-generated query to grab the data. If you are trying to ToList() an entire table's worth of data, or as in your case, have a column with a huge chunk of data, it may take some time or you may run out of memory.

Regarding the 15 columns that you have to include in the .Select(), yes, that is annoying. Unfortunately, you cannot use a constructor in a linq statement, so are forced to populate each column.

Another alternative to defining a ViewModel, which may be a little bit easier is to open up the .edmx design surface, right-click the background and Add New->Entity. You can use table XXX as a base, give it a different name, like XXXViewModel or whatever and then delete the column containing the large amount of data. Then you just need to do db.XXXViewModel.ToList().

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM