When working with a one-to-one relationship at the database level, we (I?) often end up implementing what is actually a one-to-many relationship.
For example:
CREATE TABLE master (masterId INT PRIMARY KEY)
and
CREATE TABLE child (
childId INT PRIMARY KEY,
masterId INT,
CONSTRAINT child_master_fk FOREIGN KEY (masterId) REFERENCES master (masterId))
While a single child can only reference a single master, there is nothing preventing multiple childs from referencing the same master, resulting in a one-to-many relationship.
When generating an entity data model from such a database set-up, this gets reflected with the fact that the master entity will contain a reference to the child entity, but the child entity will have a master entity collection.
Since I logically see the relationship as one-to-one, I never expect the child's master collection to contain more than one element; thus, I'd like the child entity to have a single master reference instead of a collection.
What is the correct way of accomplishing this? Creating a two-way foreign key constraint at the database level? Tweaking the generated model?
Tweak the model. Add a singular reference property that returns the single instance and just ignore the collection property. Then set the singular property to be ignored by EF in your mapping configuration.
It isn't what I'd call elegant, but such sacrifices often have to be made when using EF with a pre-existing database.
Related
Having two entities defining relationship by #ManyToOne and #OneToMany, how can I get foreign key without asking from related object and just by looking at defining tables? How do I get OWNER_ID from Owned by something like owned.getOwnerId() instead of owned.getOwner().getId() and still be able to owned.getOwner()?
Map the field in your entity as a basic mapping allows you to use the foreign key directly. You can keep the object reference mapping as well, but one of the two mappings must then be marked as insertable=false, updatable=false so that JPA knows which mapping controls the field in the event they show different values.
I´m using EF databaseFrist and creating a model, now having a problem trying to understand how to delete an entity or a relationship.
Lest say a have and Table "A" and a Table "B", and a "a_b" table that relates A and B by id (many to many), a_b only has id_A and id_B, so there is no entity a_b created on the model. A has a list<B> and B has a list<A>, i need to know how can i perform the next functions:
-Remove all B entities related to A, it means delete the rows of B.
-Remove only the relationships of A to B, so all entities still exist on DB but they are dissociated.
-Delete A and remove all B related as well (remove entities from DB).
-Delete A and preserve all B entities.
-How will it change if a_b has any other property so it becomes an entity
thanks for your time.
pd: I´m using Lambda syntax.
You can tell EF on DB First model creation to expose all primary and foreign-key properties in the entities. What it means to you is that you can query separately by querying for child objects to a parent by using the foreign-key property of the child object linked to the parent object's primary key. You can delete each child object to the parent by the child's primary-key property value to remove the relationship between parent and child. You can delete the parent if no child object is linked to the parent. That's if one is doing things normally in a deletion process using EF where one takes complete control of the deletion process.
So, you can kind of do something like that.
I'm using this trick to perform conditional Include's with EF. http://blogs.msdn.com/b/alexj/archive/2009/10/13/tip-37-how-to-do-a-conditional-include.aspx
The problem I'm having is that any collections that don't have records, are null, and not empty. This is causing headaches cos I have to check each collection before I can loop through it in my mvc view, otherwise i get a null reference exception.
For example, the StudentModules collection will be null. How can I turn it into an empty list in my query? ie without having to loop through it all and checking.
I can put a constructor in the poco to initialize the list, which fixes it, but the this collection is a virtual member in the poco (based on an EF video!) - surely this is not the way to go?
var query = from module in db.Modules
where module.Id == id
select new
{
module,
QualificationModules = from qualificationModule in module.QualificationModules
where qualificationModule.IsDeleted == false
select new
{
qualificationModule,
qualificationModule.Qualification,
StudentModules = from studentModule in qualificationModule.StudentModules
where studentModule.IsDeleted == false
select new
{
studentModule,
studentModule.Student
}
},
Assessments = (from assessment in module.Assessments
where assessment.IsDeleted == false
select new
{
assessment,
assessment.AssessmentType
}
)
};
var modules = query.AsEnumerable().Select(x => x.module);
return modules.ToList().First();
Relationship fixup runs when an entity gets attached to a context - either manually by calling Attach or when the entity is materialized as a result of a query (your case).
It is based on foreign keys of an entity and works in both directions:
If the context already contains an entity A with a foreign key f to entity B and an entity B is being attached to the context that has a primary key with the same value f as the foreign key in A (i.e. the two entities are related by an FK relationship) then Entity Framework will do the following:
If A has a navigation reference property to B it will assign the attached entity B to this property.
If B has a navigation reference property to A (one-to-one relationship) it will assign A to this property.
If B has a navigation collection property to A (one-to-many relationship) it will add A to this collection in the attached entity B. If the collection is null it will instantiate the collection before adding.
If an entity B is being attached to the context that has a foreign key f to an entity A that the context already contains and that has f as primary key EF will set the navigation properties based on the same rules like above.
As a side note: The fact that relationship fixup is based on foreign keys (they are always loaded when you query an entity, no matter if the FK is exposed as property in the model class or not) is also the reason why relationship fixup does not apply to and does not work for many-to-many relationships because the two entities of a many-to-many relationship don't have a foreign key.
Now, if there are no related StudentModules in your case there is no StudentModule entity that gets loaded into the context and there is nothing what EF could target for a fixup. Keep in mind that the fixup algorithm is not related to a particular query and does not only fix relationships between entities that this query would materialize but it will consider all entities for fixup that the context already contains, no matter how they came into the context. If you would want that collections get instantiated as empty collections EF had run through all attached parent entities of StudentModules and just create an empty collection. It makes no sense to do this during fixup instead of creating empty collections up-front before entities get attached to a context.
I can put a constructor in the poco to initialize the list, which
fixes it, but the this collection is a virtual member in the poco
(based on an EF video!) - surely this is not the way to go?
In my opinion it is the best solution if you don't want to have null collections in your model class instances. It doesn't matter if the collection is declared as virtual (to enable lazy loading) or not. A collection type does not have a derived proxy type, only the instances that get added to the collection are derived proxies. In both case you can just use StudentModules = new HashSet<StudentModule>(); (or List if you prefer).
Lets say I have 2 tables on my physical model, Receipt(ID, Location) and LineItem(ID, ReceiptID, ItemName) where a Receipt has multiple LineItems and ReceiptID is a Foreign Key to Receipt's ID.
I want to model these as a single table in my conceptual model, where I only see a table of LineItems with the Location included on each LineItem.
Every time I try to model this in the Entity Modeler, I get an error about how the Primary Key must be the same for every table being combined into the single conceptual entity.
Is this even possible to model using the entity framework?
Thanks!
No there is no way to model this directly. You must either create database view and map that view or import both entities and create QueryView in the model. In both cases resulting entity combining your two tables will become readonly and the only way to support CUD operations will be mapping stored procedures.
I have an linq to entity mapping issue. I have three tables.
Table 1 - ItemsB(ID(key), Part_Number(will be null until built), other item b information)
Table 2 - ItemsA(ID(key), Part_Number(will be null until built), other item a information)
Table 3 - WebItems(Item_id, web item information) *Consists of items from both ItemsB and ItemsA after they are built and pushed over to this table.
ItemsA/ItemsB will have a 1 to 0.1 relationship with WebItems. Part_Number maps to Item_id.
I am using EF4.0.
Problem is after i set up the association/mappings as stated above i get an error message stating: "Problem in mapping fragment at lines so and so: Column [Part_Number] are being mapped in both fragments to different conceptual side properties."
Usually i know what to do in this case. Get rid of the property [Part_Number]. Problem is i need to access [Part_Number] in both ItemsB and ItemsA quite frequently without going to webitems. Not to mention webitems will not always have the [Part_Number] populated at certain points depending upon whether the items have be pushed to webitems.
Does anyone know how to get around this?
Thanks in advance.
As I understand it ItemA and ItemB to WebItem in one-to-one relation. One-to-one relation in EF always demands that relation is build on primary keys and one side is mandatory (principal) because dependent entity will have primary key and foreign key in one column. Once you assign primary key in dependent entity you must have principal entity with the same primary key otherwise you will violate referential integrity defined by foreign key.
The problem is that your Part_Number is primary key and foreign key in the same time. To allow such mapping in EFv4 you must use Foreign Key association instead of Independent association. Here is brief description how to create foreign key association in the designer. Once you define referential constrain get back to mapping window of association and delete the mapping.