Entity Framework Design - Multiple "Views" for the data - c#

I have a design question related to Entity Framework entities.
I have created the following entity:
public class SomeEntity {
// full review details here
}
This entity has as an example 30 columns. When I need to create a new entity this works great. I have all of the required fields in order to insert into the database.
I have a few places in my app where I need to display some tabular data with some of the fields from SomeEntity, but I don't need all 30 columns, maybe only 2 or 3 columns.
Do I create an entirely new entity that has only the fields I need (which maps to the same table as SomeEntity, but only retrieves the column I want?)
Or does it make more sense to create a domain class (like PartialEntity) and write a query like this:
var partialObjects = from e in db.SomeEntities
select new PartialEntity { Column1 = e.Column1, Column2 = e.Column2 };
I am not sure what the appropriate way to do this type of thing. Is it a bad idea to have two entities that map to the same table/columns? I would never actually need the ability to create a PartialEntity and save it to the database, because it wouldn't have all of the fields that are required.

Your first approach is not possible. EF doesn't support multiple entities mapped to the same table (except some special cases like TPH inheritance or table splitting).
The second case is common scenario. You will create view model for your UI and either project your entity to view model directly in query (it will pass from DB only columns you project) or you will query whole entity and make conversion to view model in your application code (for example by AutoMapper as #Fernando mentioned).
If you are using EDMX file for mapping (I guess you don't because you mentioned ef-code-first) you can use third approach which takes part from both mentioned approaches. That approach defines QueryView - it is EF based view on the mapped entity which behaves as a new read only entity. Generally it is reusable projection stored directly in mapping.

What you proposed as a first solution is the "View model paradigm", where you create a class for the sole purpose of being the model of a view to retrieve data and then map it to the model class. You can use AutoMapper to map the values. Here's an article on how to apply this.

You could create a generic property filter method that takes in an object instance, and you pass in a string array of column names, and this method would return a dynamic object with only the columns you want.

I think it would add unnecessary complexity to your model to add a second entity based on the same data structure. I honestly don't see the problem in having a single entity for updating\editing\viewing. If you insist on separating the access to SomeEntity, you could have a database view: i.e. SomeEntityView, and create a separate entity based on that.

Related

Is it possible to mix database first and code first models with entity framework?

I am about to begin a web application where I would like to use the Entity Framework with (mostly) code first models.
However, in addition to the application-specific models I plan to create, I have to use an external user database. Is it possible to specify one of my models as database first and to use a separate database context?
Technically, it's possible, but I wouldn't recommend it. It's far better to just use code-first across the board. Yes, ironically, you can use "code-first" with an existing database.
Just create POCOs that match the tables in your existing database. If your POCO is not named the same as your table (not all table names would be valid or appropriate class names), you can use the Table attribute to explicitly tell EF what table your POCO works with:
[Table("SomeTable")]
public class MyAwesomeEntity
{
...
}
Then, you'll need a separate context specifically for this existing database and any entities that belong to it. All you have to do is 1) tell it what connection string it should use and 2) turn off database initialization, so EF doesn't try to actually create the database.
public MyExistingDatabaseContext : DbContext
{
public MyExistingDatabaseContext()
: base("MyExistingDatabaseConnectionStringName")
{
Database.SetInitializer<MyExistingDatabaseContext>(null);
}
// DbSets here
}
And that's it. Whenever you need to work with an entity from this existing database, just new up this context or get it some other way, such as through a DI (dependency injection) container, and go to town.
You should use the code first from database option if you already have an existing database available but want to use code first.
1) In your Models folder, right click on Add, New item,
2) Select ADO.NET Entity Data Model in the Data tab.
3) Enter a model name,
4) Select Code First from database.
5) Select connection string,
6) Choose your database objects you want to include in your model.
You don't have to write the code for the context and model from scratch because it will generate the classes for you.

Why are there no other constructors except for the default one in .edmx?

I use Entity Framework in my C# projects for a database connection.
Let's say I have a table on my database which has 3 columns:
table: Car
columns: id, color, type, numberOfDoors
Here is how I create a new record for this table:
Car c = new Car();//default constructor
c.color = "blue";
c.type = "Opel";
c.numberOfDoors = 2;
myDatabase.tblCar.AddObject(c);
myDatabase.SaveChanges();
I'm doing this in a lot of places in my project, so the first 4 lines are repeated a lot. So I was thinking, why doesn't Entity Framework have a constructors with parameters? I thought that maybe the columns which can be null in db can be the reason for this.
Entity Framework is trying to be as general as possible. Plus some models might have 10+ properties off of them. That would be quite messy if you only needed to assign a small subset of them. Another reason is that it would be messy to construct the models inside of Entity Framework.
The classes are generated with the partial keyword and you should be able to add it yourself.
EF generates static constructor CreateX methods for each Entity (class) it generates. For example, on one of my User classes I can do the following:
User user = User.CreateUser(userID, password, email, userTypeId);
This does most of what you would want in terms of quickly setting up a new instance of an entity class. Of course this does NOT add the new instance to the collection or save changes; you might want to create 50,000 instances and saving every time would be wasteful.

Entitiy Framework, use same model for two tables with same layout but different table names

I have two tables that have the same layout -
Report Table
ID
ReportCol1
ReportCol2
In another database I have
Reporting Table
ID
ReportCol1
ReportCol2
I want to use a single entity model called Report to load the data from both of these tables.
In my context class I have
public DbSet<Report> Report{ get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new ReportMap());
}
In my call to the first database Report table I get the results as expected.
I change the connection string to point to the second database, but I can't change the name of the table in the table mapping.
I don't want to use stored procs for the reason outlined in my comment.
What can I do, short of the tables names in the database(that is not an option).
Have you tried this fluent API modelBuilder.Entity<Report>().ToTable("Reporting"); ? You may need to write this so it conditionally does this based on which database you are connecting to. You may need to have your configuration allow you to say "DatabaseA uses this mapping and connection string", and "DatabaseB uses this other mapping and conenctions string", and rather than changing the connection string, you specify which database by some name/key, and your app looks up that name to determine which mapping code to run.
if(dbMappingconfig == DbMapping.A)//some enum you create
{
modelBuilder.Entity<Report>().ToTable("Reporting");
}
If your goal is to be able to pass these entities to other methods like DisplayReport(Report r) so that you don't have to duplicate code, you could have both Reporting and Report classes implement a IReport interface.
EF also supports inheritance hierarchies, so you could have them inherit from the same class, BUT I havfe a strong feeling that will not work across databases.
If the OnModelCreating doesn't rerun, it's probably already cached. Put modelBuilder.CacheForContextType = false; in there so it doesn't cache it in future, and to clear the current cache I think you can just do a Clean+Rebuild. This will come at the price of rebuilding the model everytime instead of reusing a cache. What you'd really want is use the cache up until the connection string changes. I don't know of anyway to manually clear the cache, but there might be a way. You can manage the model building yourself:
DbModelBuilder builder = new DbModelBuilder();
// Setup configurations
DbModel model = builder.Build(connection);
DbCompiledModel compiledModel = model.Compile();
DbContext context = new DbContext(connection, compiledModel);
But that will introduce additional complexities since you will need to manage the caching yourself.
While searching on this, I came across this that looks like they are trying to accomplish the same thing, as well as having gone down the same page, see Final section in question: How to map an Entity framework model to a table name dynamically
Are you able to create the same named view in each database and map to that instead of a variable table name?
I have 2 copies of tables with different names in my solution and deal with that by having 2 contexts and 2 sets of map files (generated text templates)

Retrieving SQL View with Entity

I have a view in my database called "viewUsers" that I need to operate on with my other entity generated tables. How can I retrieve this database view in entity?
In the Wizard, you can select Views. EF will take care of rest. Detailed example here
EDIT : As per the comment (how to do it in codefirst),
As of Entity Framework 4.2, Codefirst has built in support only for tables. That means It is only capable of generating schemas that contains tables. But If you are working with an existing database, You can map a an Updatable View with an entity. You can use the entity framework to select, insert, update and delete data. This works same as of a table. Since the SQL syntax is same for table and view for these operations, we are telling a lie to codefirst tha the view is a table!
Ex : IF we want to get data from a View called vwCustomerDetails for the Entity called CustomerDetail, We can do like this with Data Annotations
[Table("vwCustomerDetails")]
public class CustomerDetail
{
// properties
}
Alternatively, With Fluent API, you can do this,
modelBuilder.Entity<CustomerDetail>().ToTable("vwCustomerDetails");
Loading Data From a Normal View
Sometime you may want to load some data from another view which returns the same result as of our initial fake table (the view). Ex : In some Page we need to show the top Ten CustomerDetails who scored highest points. Assume we have a separate View called vwTop10Customers for that. we can use the SqlQuery method on DBSet to load the entotues like this
var topCustomers=dbContext.CustomerDetails.SqlQuery("SELECT * FROM vwTop10Customers");
The View Must return the exact same column names as of the Entity. Otherwise EF will have a problem for mapping that.

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.

Categories