Suppose I have a table with whole bunch of fields and an EF entity generated for it. Suppose I want to show an edit form for this entity, BUT with an extra field that doesn't directly map to the table.
So I create a model class that inherits my entity class and my field to it. So far so good.
The issue is that now I have to copy every single field from the entity object to the model object when returning a view and the other way around when saving data. Surely there is a cleaner way to do this?
Specific example would be a user administration form and extra fields would be password and confirm password fields, which are stored in the Membership table.
It's good practice to separate between data-transfer objects used for communicating between application tiers such as UI, and raw entities connected to the storage. Yes, you'll need to copy fields back and forth, but there are tools that can help you with this task, such as AutoMapper.
You can make the EF entity partial (I think they usually are by default), and then add the field in a separate file which also has a partial class for that class. It's not as good practice as Ilya's answer, but it's easy.
Related
While looking at this answer to the question Why do we use ViewModels?, I came across this section:
"A view should not contain any non-presentational logic" and "You
should not trust the View" (because a View could be user-provided). By
providing a Model object (potentially still connected to an active
DatabaseContext) a view can make malicious changes to your database.
What exactly does this refer to? If I have UserId and Password in my Model and my ViewModel, where does the security come in? Some kind of check in the controller? What do we check?
How do we determine we can trust the data from the view? Is this handled by the antiforgery token?
I believe the answer is referring to the over-post problem. When you utilize an entity class directly with your view, and particularly if you save that posted entity directly to your database, a malicious user could modify the form to post fields they should not be able to modify.
For example, let's say you had a form that allows a user to edit widgets. Let's also say that you have row-level permissions, such that a user can only edit widgets that belong to them. So, Joe, our fictitious malicious user, edits a widget he's allowed to edit with id 123. But, he decides he wants to mess with Jane's widget, so he adds a field to the form named Id and gives it the value of Jane's widget id. When Joe then posts the widget form, Jane's widget is updated instead.
A view model is not solely for solving this problem, but it does basically negate the issue because, inherently, you cannot directly save the view model to the database. Instead, you must map the view model's values onto the entity, before saving the entity to the database. As a result, you then explicitly control what does and does not get mapped, so in the same example above, Joe changing the id ends up having no effect because you're not mapping that onto the entity.
In truth, the real problem here is in directly saving anything posted by a user directly to the database. You could actually still feed your entity class to the view as the "model", but then not save the posted instance. Instead, you then create a new instance of the entity or pull an instance from the database fresh, and simply map the values from the posted instance over to that. Again, you wouldn't map a property like Id, so again Joe is foiled. In other words, it's not the view model that solves the problem, it's the never trusting a user enough to directly save anything created via a POST that solves the issue.
Microsoft gives another alternative solution in the form of the Bind attribute, which essentially allows you to include/exclude certain properties on an entity class from the modelbinding process (ignoring any posted values, in other words). So, for example, you could potentially solve the issue above by decorating the param on your action with [Bind(Exclude = "Id")], which would then discard any posted value for Id. However, Bind is horrible for a number of reasons, and you should not actually use it. Always use a view model instead, or simply don't ever directly save the entity instance created by the modelbinder.
Let's say I have a project where I use Entity Framework, but I want to use my own classes instead of the EF classes.
Reasons for using my own classes:
Easy to add properties in code
Easy to derive and inherit
Less binding to the database
Now, my database has table names like User and Conference.
However, In my domain project, I also call my files User.cs and Conference.cs.
That means I suddenly have two objects with the same naming, which is usually very annoying to work with, because you have to use namespaces all the time to know the difference.
My question is how to solve this problem?
My ideas:
Prefix all database tables with 'db'. I usually do this, but in this case, I cannot change the database
Prefix or postfix all C# classes with "Poco" or something similar
I just don't like any of my ideas.
How do you usually do this?
It's difficult to tell without more background but it sounds like you are using the Entity Framework designer to generate EF classes. This is known as the "Model First" workflow. Have you considered using the Code First / Code Only workflow? When doing code first you can have POCO classes that have no knowledge of the database, EF, or data annotations. The mapping between the database and your POCOs can be done externally in the the DBContext or in EntityTypeConfiguration classes.
You should be able to achieve your goal of decoupling from EF with just one set of objects via code first.
To extend the above answer, the database table name User (or Users as many DB designers prefer) is the identifier for the persistence store for the object User that's defined in your code file User.cs. None of these identifiers share the same space, so there should be no confusion. Indeed, they are named similarly to create a loose coupling across spaces (data store, code, development environment) so you can maintain sanity and others can read your code.
Assume i have a big entity and want to create a typical CRUD application. A user shouldn't have the ability to save some fields of my entity.
So i see two ways to implement change-save logic:
a)
Get entity from DB
Out to page with all fields(fields which user shoudnt change outed as hidden inputs)
Take entity by post method
Attach to context and save
In this case i need to out on page useless fields. And it is sucks no doubt.
b)
Get entity from DB
Out to page only necessary fields(fields which user can change)
Take entity by post method
Get entity from DB
Fill DB entity by new values and save
In this case i need to do additional query to DB. So it is not good for perfomance.
What is right way?
or C):
Get entity from DB
Map entity to ViewModel with only the allowed fields
Post ViewModel with data back to controller
Map ViewModel back to Entity
Attach and Save.
EDIT:
I highly recommend AutoMapper for the mapping to and fro
Interestingly enough, I just watched a video made by Julie Lerman in which she discusses almost the exact same problem. Neither of your solutions was what she went with:
Have a separate entity class that contains the fields that you want to go on the screen, but still maps to the same table that the regular one does. Then just query that DbSet for grabbing the entity (with only those fields), and save the updates to that.
She mentioned this while discussing implementing Domain Driven Design on top of Entity Framework. So that if you have different DbContexts for different functions in your application, you can still have a DbContext that you're using write to the table, but you can restrict which fields that context can write to.
It is recommended to use different ViewModels for different tasks. If you want to show the user some fields of the Model to edit, then you can do so using EditModel and while saving use CreateModel to create and populate the database. This way you can avoid your database structure to be known to the user, thus ensuring protection and security.
In C# is it possible to create a model of entities regardless of the database initially. Are there tools to create graphic entities in this way? What do you recommend?
Well, it's in your question as a tag - entity framework is a good tool for this. You can create classes, that you push later to the database.
Search for "code-first". Google will provide plenty of results I'm sure.
Edit based on the comment:
Well, in that case, try this: when you're creating edmx file, pick the second option - empty model.
From its description:
Creates an empty model as a starting point for visually designing a
conceptual model from the toolbox. Classes are generated from the
model when the project is compiled. You can specify a database
connection later to map the conceptual model to the storage model.
this may be the thing you want then.
I have a table that used throughout an app by Entity. I have a view that returns an identical column set, but is actually a union on itself to try to work around some bad normalization (The app is large and partially out of my hands, this part is unavoidable).
Is it possible to have Entity 4 treat a view that is exactly like a table as the same type, so that I can use this view to populate a collection of the same type? This question seems to indicate it is possible in nhibernatem but I can't find anything like it for entity. It would be an extra bonus of the navigation properties could still be used to Include(), but this is not necessary (I can always manually join).
Since EF works on mappings from objects to database entities this is not directly possible. What you need is something like changing the queried database entity dynamically, and AFAIK this is not possible without manually changing the object context.
For sure the EF runtime won't care as long as it can treat the view as if it was completely separate table. The two possible challenges that I forsee are:
Tooling: Our wizard does allow you to select views when doing reverse engineering (i.e. database-first). Definitively if you can use 'code first against an existing database' you can just pretend that the view is just a table, but you won't get any help scripting the database creation or migrations.
Updates: in general you can perform updates for a view setting up store procedure mapping (which is available in the EF Designer from v1 or in Code First starting in EF6). You might also be able to make your view updatable directly or using instead off triggers (see "Updatable Views" here for more details). If I remember correctly the SQL generated by EF to retrieve database generated values (e.g. for identity columns) is not compatible in some cases with instead-off triggers. Yet another alternative is to have your application treat the view as read-only and perform all updates through the actual table, which you would map as a separate entity. Keep in in mind that in-memory entities for the view and the original table will not be kept in sync.
Hope this helps!