I'm wondering what's the best method for validating a view field value to be unique in an entityset: before or after the update to persistence layer?
The involved db field has an unique constraint, and its table is mapped to an EF model.
I see two ways for unique value validation in an entityset:
before saving changes to db (during model update or by decorating with custom DataAnnotations the model)
after saving changes to db (by handling in the repository or controller the UpdateException generated by the persistence layer)
With the 1st method I need to query the db for checking the uniqueness, so any view update will require both a db select and a db update.
With the 2nd method, the additional select is not required, but it is difficult to identify the error type and the offending field.
I would prefer method 2, but the problem for determining if the insert/update failed due to a unique constraint force me to choose method 1.
Or is there another way?
The preferred and recommended way for checking unique constraint is from UI by custom DataAnnotation attribute. with this method you have to write a little code but this is what all the sites have been doing for checking uniqueness constraint. asp.net mvc 3 however provides RemoteAttribute out of the box to check uniqueness constraint. i would recommend using first method because some tiny ajax calls won't make noticeable effect on performance provided that you have organized it in a good manner.
Related
We have an entity and a corresponding table in the database with one additional column which contains digested hash of the entity fields, calculated each time programmatically in application. Entity has associations with two additional tables/entities which fields also take part in hashing.
Now a decision was made to get rid of one of the fields from the main entity (boolean flag) and exclude it from hashing, since it makes two otherwise identical entities get different hashes when one entity has its flag set to true, while other is false. Since hashes are different both entities get stored in the database, which is not what we want.
Removing the field is simple, but we also need to re-calculate hashes for entities which have been already stored in the database. Since there might be duplicates, we also need to get rid of one of two duplicated entries. This whole operation must be done once after migration.
The stack we use is Quarkus, Flyway, Hibernate with Panache, and PostgreSQL. I have tried to use Flyway callbacks with Event.AFTER_MIGRATE to get all existing entities from the db, but I can't use Panache since its not initialised yet by the time callback hits. Using plain java.sql.* Connection and Statement is pretty cumbersome, cause I need to fetch data from 3 tables, create entity from all of the fields, re-calculate hash and put it back, while taking care of possible conflicts. Another option would be to create a new REST API endpoint specifically for the job which the client will have to call after app has booted, but somehow I don't feel that that is the best solution.
How do you tackle this kind of a situation?
So I'm creating a database model using Entity Framework's Code First paradigm and I'm trying to create two tables (Players and Teams) that must share a uniqueness constraint regarding their primary key.
For example, I have 3 Players with Ids "1", "2" and "3" and when I try to create a Team with Id "2", the system should validate uniqueness and fail because there already exists a Player with Id "2".
Is this possible with data annotations? Both these entities share a common Interface called IParticipant if that helps!
Txs in advance lads!
The scenario you are describing here isn't really ideal. This isn't really a restriction on Entity Framework; it's more a restriction on the database stack. By default, the Id primary key is an Identity column, and SQL itself isn't really supportive of the idea of "shared" Identity columns. You can disable Identity and manage the Id properties yourself, but then Entity Framework cannot automatically build navigation properties for your entities.
The best option here is to use one single participant table, in a technique called "Table Per Hierarchy", or TPH. Entity Framework can manage the single table using an internal discriminator column. Shared properties can be put into the base class, and non-shared properties can be put on the individual classes, which Entity Framework will composite into a single large table in the DB. The main drawback to this strategy is that columns for non-shared properties will automatically be nullable in the database. This article describes this scenario very well.
The more I try to come up with a solution, I realize that this is an example of the XY Problem. There is not really a good solution to this question, because this question is already a proposed solution. There is a problem here that has led you to create an Interface which you suggest requires the entities which are using the interface to have a unique Id. This really sounds like an issue with the design of the Interface itself, as Interfaces should be agnostic to the entity they are applied to. Perhaps providing some code and showing what your problem actually is would be helpful, since the proposed solution you are asking how to implement here isn't really practical.
Using EF with MVC4 allows you to specify the inclusion of Foreign Key columns in the model. While this not normally part of OR modeling, it does allow MVC4 to automatically generate views with dropdown lists, for the foreign key relationships, when you generate a controller with the MVC controller with read/write actions and views, using Entity Framework option.
I have hit a problem creating an object in this scenario.
Greatly simplified, the models in question are:
Questionnaire:
QuestionnaireID: PK
CandidateId: FK
Candidate: Associated object
Candidate:
CandidateID: PK
Name: string
The problem I have hit is that on a Create view post-back to create a new Questionnaire ModelState.IsValid is false. On investigation the error listed is The parameter conversion from type 'System.String' to type 'Data.Candidate' failed because no type converter can convert between these types.
ModelState.Keys includes Questionnaire.Candidate as well as Questionnaire.CandidateId (which is valid).
I am sure this is something simple, but would like to hear some solutions. The viewbag only has a set for the drop-down list and the view has an #model of type #model Data.Questionnaire. There are no editor fields bound to Questionnaire.Candidate..
As I have no idea why the built-in EF models do not like the MVC generated scaffolding, for Create postbacks with foreign key columns enabled, I have reverted to what is a more secure solution (still happy to hear why it fails out-of-the-box):
Create individual view models for specific sensitive operations like create
The theory goes that there are a number of problems using EF domain entities as viewmodels including:
They potentially expose too much information or allow additional fields to be posted back
Validation text is an interface concern and should not be part of a the data model (they actually suggest even the viewmodel is not the place for this text, but I digress).
So basically I now have a CreateCandidateQuestionnaireVM class with only the required fields for selecting appropriate values for a new instance.
We are currently using EMF Validation to provide direct feedback to the user in case of model constraint violation.
The system is set up as follows:
An EContentAdapter records all modifications done on the model
A CommandStackListener pushes these modifications to the EMF Validation framework upon finishing a Command. This reduces the number of validations executed. The EMF LiveValidator is configured to also report SUCCESS.
Every constraint looks at the Notification based on the following criteria:
Is it a Modification of the contents of the entity being validated?
Is it a Modification which adds the entity being validated?
Is it a Modification which will influence a previously calculated Validation result in some other way?
A ValidationListener keeps a list of all entities that have failed Constraints. It updates this list with the new SUCCESS or FAILED ConstraintStatus messages. It also updates the list to remove FAILED entities that are no longer contained in the Resource (because they were removed).
It seems that I have implemented a lot of functionality myself. Is there no standard API / Implementation available to do the following?
Track Validation Status
Track the attributes a Constraint uses; only revalidate if one of these attributes change.
Comparable to how JFace Databinding's ComputedValue works.
Or am I actually using the framework to the fullest?
If I would be using OCL Constraints, would the system then be able to detect which changes impact the Constraint result?
I have some views that I want to use EF 4.1 to query. These are specific optimized views that will not have keys to speak of; there will be no deletions, updates, just good ol'e select.
But EF wants a key set on the model. Is there a way to tell EF to move on, there's nothing to worry about?
More Details
The main purpose of this is to query against a set of views that have been optimized by size, query parameters and joins. The underlying tables have their PKs, FKs and so on. It's indexed, statiscized (that a word?) and optimized.
I'd like to have a class like (this is a much smaller and simpler version of what I have...):
public MyObject //this is a view
{
Name{get;set}
Age{get;set;}
TotalPimples{get;set;}
}
and a repository, built off of EF 4.1 CF where I can just
public List<MyObject> GetPimply(int numberOfPimples)
{
return db.MyObjects.Where(d=> d.TotalPimples > numberOfPimples).ToList();
}
I could expose a key, but whats the real purpose of dislaying a 2 or 3 column natural key? That will never be used?
Current Solution
Seeming as their will be no EF CF solution, I have added a complex key to the model and I am exposing it in the model. While this goes "with the grain" on what one expects a "well designed" db model to look like, in this case, IMHO, it added nothing but more logic to the model builder, more bytes over the wire, and extra properties on a class. These will never be used.
There is no way. EF demands unique identification of the record - entity key. That doesn't mean that you must expose any additional column. You can mark all your current properties (or any subset) as a key - that is exactly how EDMX does it when you add database view to the model - it goes through columns and marks all non-nullable and non-computed columns as primary key.
You must be aware of one problem - EF internally uses identity map and entity key is unique identification in this map (each entity key can be associated only with single entity instance). It means that if you are not able to choose unique identification of the record and you load multiple records with the same identification (your defined key) they will all be represented by a single entity instance. Not sure if this can cause you any issues if you don't plan to modify these records.
EF is looking for a unique way to identify records. I am not sure if you can force it to go counter to its nature of desiring something unique about objects.
But, this is an answer to the "show me how to solve my problem the way I want to solve it" question and not actually tackling your core business requirement.
If this is a "I don't want to show the user the key", then don't bind it when you bind the data to your form (web or windows). If this is a "I need to share these items, but don't want to give them the keys" issue, then map or surrogate the objects into an external domain model. Adds a bit of weight to the solution, but allows you to still do the heavy lifting with a drag and drop surface (EF).
The question is what is the business requirement that is pushing you to create a bunch of objects without a unique identifier (key).
One way to do this would be not to use views at all.
Just add the tables to your EF model and let EF create the SQL that you are currently writing by hand.