Does Entityframework automate navigation properties to create

When I run the code below, EF saves PersonAddress with the correct PersonId . I have NOT added PersonAddress entities to the Person object, although I have not done this yet, the records in my database are connected correctly.

My question is: does EF automatically add related objects, even if I did not specify the object to which it belongs? And if so, will this not lead to an undesirable essential relationship?

Update

It seems that the objects were saved correctly for the following reasons:

  • When creating a Person object, the PersonId field is 0
  • PersonAddress.PersonId also 0 at creation time.

Manually setting Person.PersonId to any value at creation time, and then setting PersonAddress.PersonId to the same Person.PersonId EF value saves the data correctly because they have the same PersonId .

Thus, technically, EF does not automatically add related objects; they are related to each other because they have the same PersonId .

Please check out the code below:

  using (var context = new Models.TestEntities()) { var person = context.People.Create(); var postalAddress = context.PersonAddresses.Create(); postalAddress.AddressLine1 = "PostalAddressLine1"; var residentialAddress = context.PersonAddresses.Create(); residentialAddress.AddressLine1 = "ResidentialAddressLine1"; context.People.Add(person); context.PersonAddresses.Add(postalAddress); context.PersonAddresses.Add(residentialAddress); context.SaveChanges(); } 

When I add additional Person code to the code, I get the following error: enter image description here
Code:

  using (var context = new Models.TestEntities()) { var person = context.People.Create(); var person2 = context.People.Create(); var postalAddress = context.PersonAddresses.Create(); postalAddress.AddressLine1 = "PostalAddressLine1"; var residentialAddress = context.PersonAddresses.Create(); residentialAddress.AddressLine1 = "ResidentialAddressLine1"; context.People.Add(person); context.People.Add(person2); context.PersonAddresses.Add(postalAddress); context.PersonAddresses.Add(residentialAddress); context.SaveChanges(); } 

Since the indicated error, Entityframework can no longer determine to whom PersonAddress belongs.

I can solve this problem by changing the code as follows:

  using (var context = new Models.TestEntities()) { var person = context.People.Create(); var person2 = context.People.Create(); var postalAddress = context.PersonAddresses.Create(); postalAddress.AddressLine1 = "PostalAddressLine1"; var residentialAddress = context.PersonAddresses.Create(); residentialAddress.AddressLine1 = "ResidentialAddressLine1"; context.People.Add(person); context.People.Add(person2); person.PersonAddresses.Add(residentialAddress); person.PersonAddresses.Add(postalAddress); context.SaveChanges(); } 

See EDMX below:

enter image description here

See the SQL script used to create two tables:

 CREATE TABLE Person ( PersonId INT IDENTITY(1,1) NOT NULL CONSTRAINT [PK_Person] PRIMARY KEY, FirstName VARCHAR(250) ) CREATE TABLE PersonAddress ( PersonAddressId INT IDENTITY(1,1) NOT NULL CONSTRAINT [PK_PersonAddress] PRIMARY KEY, PersonId INT NOT NULL, AddressLine1 VARCHAR(250) ) ALTER TABLE PersonAddress ADD CONSTRAINT [FK_PersonAddress_Person] FOREIGN KEY(PersonId) REFERENCES [Person](PersonId) 

Please see the screenshots in the Id columns below: enter image description hereenter image description hereenter image description here

Please view the SQL Server Profiler trace below:

Person :
enter image description here

PersonAddress :
enter image description here

PersonAddress :
enter image description here

Please view the inserted records in SQL:

Person :
enter image description here

PersonAddress :
enter image description here

Thanks.

+6
source share
4 answers

Here's what happens:

 var person = context.People.Create(); 

A Person is created with PersonId = 0.

 var postalAddress = context.PersonAddresses.Create(); postalAddress.AddressLine1 = "PostalAddressLine1"; var residentialAddress = context.PersonAddresses.Create(); residentialAddress.AddressLine1 = "ResidentialAddressLine1"; 

Addresses are created that also have PersonId = 0.

 context.People.Add(person); context.PersonAddresses.Add(postalAddress); context.PersonAddresses.Add(residentialAddress); 

EF performed the correction of the relationship, that is, it mapped the addresses " PersonId and Person PersonId (all 0) and established a connection between them.

 context.SaveChanges(); 

The database has assigned the value of the identifier Person.PersonId . EF reads data from the database into objects.

In the second fragment, there are two Person with PersonId = 0, so now EF does not know with which person the addresses should be associated.

What to do

Clearly this is an unexpected behavior. It’s best to link objects explicitly if they are intended to be connected, as in your third fragment.

Once you learn about these automatic associations, you can prevent them by setting a different default value for Person.PersonId other than 0, for example. -1. Now EF will not match this id with any other extraneous value having a default value for integers, 0.

+3
source

I tested the script by creating a new project against a new database created using the script. Then I generated a model against it, leaving all the defaults.

Here is the code I used to create the person and addresses.

  var entities = new TestEntities(); var person = entities.People.Create(); person.FirstName = "xxx"; entities.People.Add(person); var address1 = entities.PersonAddresses.Create(); address1.AddressLine1 = "Line1"; entities.PersonAddresses.Add(address1); var address2 = entities.PersonAddresses.Create(); address2.AddressLine1 = "Line1"; entities.PersonAddresses.Add(address2); entities.SaveChanges(); 

I can confirm that this code is indeed running and insert the person and the two addresses associated with this person. It definitely looks like EF is connecting to it if there is only one object that it could connect to. I'm not sure if this should be a function, but it might do for some unpleasant surprises.

+1
source

No, EF cannot add an automatically linked object if you do not specify what is the second entity, the reason is the data integrity restrictions in the database, I hope this helps.

0
source

Here you attach two face objects to the context

 context.People.Add(person); context.People.Add(person2); 

And here you attach two addresses to the first person object

 person.PersonAddresses.Add(residentialAddress); person.PersonAddresses.Add(postalAddress); 

So basically you tell Entity Framework that you want to map two addresses to the first person. If you do not, the Entity Framework will not display them unless you manually enter personID in the addresses

In your first code, you create only the person and addresses and try to add them to the database. There is no mapping between them, and the Entity Framework does not know that they should be connected.

0
source

Source: https://habr.com/ru/post/984839/


All Articles