Defining ORM Foreign Key Relationships

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.
12 years ago
The StateProvince entity has 2 properties, namely,
(a) int CountryId
(b) Navigation Property: Reference to Country type

We can always use the Country reference to determine the country to which the StateProvince belongs to. In this  scenario, is CountryId really needed? According to me, the Country reference is sufficient.

If we look at the StateProvinceMap, it defines the foreign key relationship as follows
                .HasForeignKey(sp => sp.CountryId);

Can't we change it to
                .HasForeignKey(sp => sp.Country.Id);             The Id property of Country entity



Secondly, this association is bidirectional. The Country entity has the StateProvinces Collection property. If we see its usage, it is getting used in InstallationService only. Along the similar lines, why the Country/StateProvince service is not making use of this Collection property while saving the StateProvinces? Looks like it does not keep objects in memory consistent, we also need to add StateProvince to Country.StateProvinces.
12 years ago
cool wrote:
Can't we change it to
                .HasForeignKey(sp => sp.Country.Id);             The Id property of Country entity
.


Let me clarify more on this. Of course, if the db is already generated, you can't change.

http://www.ladislavmrnka.com/2011/05/foreign-key-vs-independent-associations-in-ef-4/

If there, make it read-only.

cool wrote:
Secondly, this association is bidirectional. The Country entity has the StateProvinces Collection property. If we see its usage, it is getting used in InstallationService only. Along the similar lines, why the Country/StateProvince service is not making use of this Collection property while saving the StateProvinces? Looks like it does not keep objects in memory consistent, we also need to add StateProvince to Country.StateProvinces.


This seems to be a serious bug. The Country-StateProvince association is bidirectional and we have to take care of keeping both sides of the bidirectional relationship in sync. And Nop does not do so.  If I am correct, this problem is scattered throughout the Nop. For instance, another place is the Addresses collection property in the Country entity. It is getting accessed at one place only, namely, CountryController where it checks the Count of Addresses. If greater than 0, it throws an exception. Now how can we check the count unless we initialize/populate the Addresses collection somewhere else in the Nop code.

Friends, I'd appreciate if you say Yes/No to this. If yes, can we expect the solution in Nop 2.1?
12 years ago
cool wrote:
Can't we change it to .HasForeignKey(sp => sp.Country.Id);

No, you can't. EF Code-First doesn't allow it. I recommend to look at the following article about Code First Fluent API http://blogs.msdn.com/b/adonet/archive/2010/12/06/ef-feature-ctp5-fluent-api-samples.aspx

cool wrote:
For instance, another place is the Addresses collection property in the Country entity. It is getting accessed at one place only, namely, CountryController where it checks the Count of Addresses. If greater than 0, it throws an exception. Now how can we check the count unless we initialize/populate the Addresses collection somewhere else in the Nop code.

It's automatically populated when you access 'Addresses' property (lazy loading).

cool wrote:
This seems to be a serious bug. The Country-StateProvince association is bidirectional

I don't understand where exactly you found the bug. Can you describe some steps to replicate it?
12 years ago
Hint: This can be resolved through add or set methods in the object model that handle both sides of the relationships, so the application code does not need to worry about it.
12 years ago
a.m. wrote:
I don't understand where exactly you found the bug. Can you describe some steps to replicate it?


In VS, right click on the Addresses property of the Country entity and click Find All References. See it is accessed at one place only, namely, the CountryController where its Count is checked. Now, we have not initialized/set the collection anywhere in the code. So the Count will always remain to 0. It is happening because the programmer has maintained only one side of the relationship i.e. the Country reference in the Address entity.

If I am correct, we have to fix this for every bidrectional relationship that is there in the Nop. If Entity Framework is smart enough to have magic that automatically maintains relationships, then I am wrong. In Java Hibernate and .NET NHibernate, however, it is the responsibility of the programmer to keep both sides of the relationship in sync.

And the good place is the setter method, something like this ...

public class Employee {
    private List phones;
    ...
    public void addPhone(Phone phone) {
        this.phones.add(phone);
        if (phone.getOwner() != this) {
            phone.setOwner(this);
        }
    }
    ...
}

public class Phone {
    private Employee owner;
    ...
    public void setOwner(Employee employee) {
        this.owner = employee;
        if (!employee.getPhones().contains(this)) {
            employee.getPhones().add(this);
        }
    }
    ...
}
12 years ago
cool wrote:
If Entity Framework is smart enough to have magic that automatically maintains relationships, then I am wrong.

Yes, EF is smart enough. Everything works fine.
This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.