54

I have a simple code in Entity Framework (EF) v4.1 code first:

PasmISOContext db = new PasmISOContext();
var user = new User();
user.CreationDate = DateTime.Now;
user.LastActivityDate = DateTime.Now;
user.LastLoginDate = DateTime.Now;
db.Users.Add(user);

db.SaveChanges();
user.Avatar = new Avatar() { Link = new Uri("http://myUrl/%2E%2E/%2E%2E") };
db.SaveChanges();


db.Users.Add(new User() { Avatar = new Avatar() { Link = new Uri("http://myUrl/%2E%2E/%2E%2E") } });
db.SaveChanges();

The problem is that I get an error

An error occurred while saving entities that do not expose foreign key properties for their relationships. The EntityEntries property will return null because a single entity cannot be identified as the source of the exception. Handling of exceptions while saving can be made easier by exposing foreign key properties in your entity types. See the InnerException for details.

at

db.Users.Add(new User() { Avatar = new Avatar() { Link = new Uri("http://myUrl/%2E%2E/%2E%2E") } });
db.SaveChanges();
  

I don't understand why the similar operation works. Is there something wrong with my model, or with ef-code-first?

public class Avatar
{
    [Key]
    public int Id { get; set; }

    [Required]
    public string LinkInString { get; set; }

    [NotMapped]
    public Uri Link
    {
        get { return new Uri(LinkInString); }
        set { LinkInString = value.AbsoluteUri; }
    }
}

public class User
{
    [Key]
    public int Id { get; set; }
    public string UserName { get; set; }
    public string Email { get; set; }
    public string Password { get; set; }
    public Avatar Avatar { get; set; }
    public virtual ICollection<Question> Questions { get; set; }
    public virtual ICollection<Achievement> Achievements { get; set; }

    public DateTime CreationDate { get; set; }
    public DateTime LastLoginDate { get; set; }
    public DateTime LastActivityDate { get; set; }
}
RBT
  • 24,161
  • 21
  • 159
  • 240
user278618
  • 19,306
  • 42
  • 126
  • 196
  • 1
    I cannot reproduce the error. Can you check the first code snippet? Is that excactly what your are doing? (At least one `db.Users.Add(user)` seems to be missing, otherwise the 2 `SaveChanges` make no sense.) Do you have any additional Fluent API mapping? – Slauma Oct 29 '11 at 13:16
  • Thanks Slauma. I've edited my code. I haven'y any Fluent API. First and second SaveChanges add row to Avatars, and Users tables. I don't know if this is important, but in table I have Avatar_Id column. – user278618 Oct 29 '11 at 14:57
  • 8
    `Avatar_Id` in `User` table is the foreign key column for the `Avatar` navigation property, that's OK. Did you create the database tables manually or did you let EF create the database? At the moment I have no idea why you get this error. You could try to follow the advice given in the exception and add a foreign key property to your `User` class: `public int? AvatarId { get; set; }` and see what happens. Perhaps at least the exception will reveal more details where the problem exactly is. – Slauma Oct 29 '11 at 17:37
  • I let EF cretate the database. As you said I've added this property and now it works fine - now I have AvatarId instead Avatar_Id and it keeps correct avatarid. It weird , but thanks for helping me. – user278618 Oct 29 '11 at 20:58
  • You could post it as an answer that the FK property fixed the problem and then accept your answer, just to finish this question. I don't understand why it solved your problem, for me it also worked without the FK property. – Slauma Oct 29 '11 at 21:27

16 Answers16

182

For those of you who would still have this error with all keys properly defined, have a look at your entities and make sure you don't leave a datetime field with a null value.

Baral
  • 3,103
  • 2
  • 19
  • 28
  • 11
    If you look at the inner exceptions, there is an exception of type "System.Data.SqlClient.SqlException" with message: "The conversion of a datetime2 data type to a datetime data type resulted in an out-of-range value." This results from having a null DateTime value being inserted into a column with null values not allowed. See http://stackoverflow.com/questions/1331779/c-sharp-conversion-of-a-datetime2-data-type-to-a-datetime-data-type. – Ryan Kyle Jan 04 '15 at 05:11
  • My inner exception did not have anything related to datetime2 conversion, but I was setting a datetime to null. The DB column allows nulls, so I assumed that wasn't the problem, but it turned out it was. Try this even if you don't think it's your problem! – vaindil Mar 01 '16 at 16:35
  • hello @SarangK can you tel how do you fix this problem – Med Elgarnaoui Sep 18 '16 at 17:41
  • Thank you, it helped and saved me a lot of time ! – hotfusion Mar 07 '17 at 14:21
  • @MohamedElgarnaoui I checked all DateTime fields to be initialized before 'context.SaveChanges();' – SarangK Jun 09 '17 at 12:19
  • This really goes for any datatype. I have a project which passes data through several methods and a string field was not getting set in one of the DTOs. C# didn't care but the database field is non-nullable so SQL Server did. – Wildcat Matt Jul 31 '19 at 14:38
16

This error message can be thrown for any kind of reason. The 'InnerException' property (or its InnerException, or the InnerException of that, etc) contains the actual primary cause of the problem.

It would of course be useful to know something about where the problem occurred - which object(s) in the unit of work is causing the problem? The exception message would normally tell you in the 'EntityEntries' property, but in this case, for some reason, that can't be done. This diagnostic complication - of the 'EntityEntries' property being empty - is apparently because some Entities 'do not expose foreign key properties for their relationships.'

Even if the OP gets the error because of failing to initialize DateTimes for the second instance of User, they get the diagnostic complication - 'EntityEntries' being empty, and a confusing top-level message ... because one of their Entity's doesn't 'expose foreign key properties'. To fix this, Avatar should have a public virtual ICollection<User> Users { get; set; } property defined.

David Bullock
  • 6,112
  • 3
  • 33
  • 43
6

The issue was resolved by adding an FK property.

Taryn
  • 242,637
  • 56
  • 362
  • 405
user278618
  • 19,306
  • 42
  • 126
  • 196
  • 1
    I stumbled upon this answer. I was receiving this fault during database initialization (dropcreatedb). I already had a foreign key, but making it nullable resolved my issue – Ben Felda Feb 28 '13 at 20:00
  • I have no idea why OP didn't mark this as the accepted answer, because it clearly solved the issue. See the comments below the question. – Gert Arnold Dec 08 '22 at 11:51
3

In my case the following situation was giving me the same Exception:

Imagine a code first EF model where you have a Garage entity that has a collection of Car entities. I needed to remove a car from the garage so I ended up with code that looked like this:

garageEntity.Cars.Remove(carEntity);

Instead, it should've been looked like this:

context.Cars.Remove(carEntity);
Memet Olsen
  • 4,578
  • 5
  • 40
  • 50
  • 1
    Assuming a Car MUST have a Garage, yes. Because else you'd be trying to pass a null for GarageId in your Car object. – Flater Mar 26 '14 at 09:43
2

Just for others who might have similar problems. I had the same error, but for a different reason. In one of the child objects I defined the [Key] as being a value which was the same for different saves. A stupid mistake on my part, but the error message does not instantly lead you to the problem.

Simon The Cat
  • 604
  • 1
  • 8
  • 22
2

In my case the exeception was thrown because EF had created a migration incorrectly. It missed setting the identity: true on the second table. So go into the migrations which created the relevant tables and check if it missed to add identity.

CreateTable(
    "dbo.LogEmailAddressStats",
    c => new
        {
            Id = c.Int(nullable: false, identity: true),
            EmailAddress = c.String(),
        })
    .PrimaryKey(t => t.Id);

CreateTable(
    "dbo.LogEmailAddressStatsFails",
    c => new
        {
            Id = c.Int(nullable: false), // EF missed to set identity: true!!
            Timestamp = c.DateTime(nullable: false),
        })
    .PrimaryKey(t => t.Id)
    .ForeignKey("dbo.LogEmailAddressStats", t => t.Id)
    .Index(t => t.Id);

An Id column should have identity (i.e. auto-incrementing!) so this must be a EF bug.

You could add identity manually with SQL directly to the database but I prefer using Entity Framework.

If you run in to the same problem I see two easy solutions:

Alt 1

reverse the incorrectly created migration with

update-database -target:{insert the name of the previous migration}

Then add the identity: true manually to the migration code and then update-database again.

Alt 2

you create a new migration that adds identity. If you have no changes in the models and you run

add-migration identity_fix

it will create an empty migration. Then just add this

    public partial class identity_fix : DbMigration
    {
        public override void Up()
        {
            AlterColumn("dbo.LogEmailAddressStatsFails", "Id", c => c.Int(nullable: false, identity: true));
        }

        public override void Down()
        {
            AlterColumn("dbo.LogEmailAddressStatsFails", "Id", c => c.Int(nullable: false));
        }
    }
fredrik.hjarner
  • 715
  • 8
  • 22
1

This problem can also arise from reversed key declarations. If you're using fluent to configure the relationship, make sure the left and right keys are mapped to the correct entity.

Edyn
  • 2,409
  • 2
  • 26
  • 25
1

I hade same probleme. in my case, it was due to datetime field with a null value. I had to passe a value to datetime and evrythings went fine

onlyme
  • 3,776
  • 2
  • 23
  • 17
0

Another answer:

I used this:

public List<EdiSegment> EdiSegments { get; set; }

instead of this:

public virtual ICollection<EdiSegment> EdiSegments { get; set; }

and got the error message noted above.

Greg Gum
  • 33,478
  • 39
  • 162
  • 233
0

I had the same error and in my case the problem was that I added a relationship object which had already been loaded "AsNoTracking". I had to reload the relation property.

BTW, Some suggest using "Attach" for relations that already exist in db, I haven't tried that option though.

Hamed
  • 279
  • 1
  • 3
  • 13
0

In my case, the problem was that I renamed a column improperly, so the migration made two columns, one called "TeamId" and one called "TeamID". C# cares, SQL doesn't.

Duston
  • 1,601
  • 5
  • 13
  • 24
0

Yet another different case here. A query was cast to a list and while doing that, it created entities by their constructor for comparison in the linq expression right after the ToList(). This created entities that gotten into the deleted state after the linq expression finished.
However! There was a small adjustment that created another entity in the constructor, so that this new entity got linked to an entity that was marked as Deleted.

Some code to illustrate:

query.Except(_context.MyEntitySetSet()
                .Include(b => b.SomeEntity)
                .Where(p => Condition)
                .ToList() // This right here calls the constructor for the remaining entities after the where
                .Where(p => p.Collection.First(b => Condition).Value == 0)
                .ToList();

The constructor of MyEntity:

public partial class MyEntity
{
    protected MyEntity()
    {
        // This makes the entities connected though, this instance of MyEntity will be deleted afterwards, the instance of MyEntityResult will not.
        MyEntityResult = new MyEntityResult(this);
    }
}

My solution was to make sure the entire expression was done inside the IQueryable so that there won't be any objects created.

Mixxiphoid
  • 1,044
  • 6
  • 26
  • 46
0

I'm not entirely sure that it's going to help in your case because I'm setting up my tables using Fluent API, however, as far I can tell, the issue arises regardless whether the schema is set up using data annotations (attributes) or Fluent API (configuration).

There seems to be a bug in EF (v. 6.1.3) as it omits certain changes to the schema when updating the DB to the next migration. The quickest route around it is (during the development stage) to remove all the tables from the DB and runt migrations from init stage again.

If you're already in production, the quickest solution I've found was to manually change the schema in the DB or, if you want to have version control of the changes, manually manipulate the methods Up() and Down() in your migration.

Konrad Viltersten
  • 36,151
  • 76
  • 250
  • 438
0

Today I faced this issue and tried the possible solutions posted above but none of them helped me. I had UnitOfWork pattern implemented and system was committing the data in last after adding all the records.

In my case system was combining the two models and querying the DB

Invalid object name 'dbo.RoleModelUserModel'.

where these were two different models actually.

I fixed this by reordering the insert statements and adding the parent entity first. In this case added the user first and issue resolved.

stop-cran
  • 4,229
  • 2
  • 30
  • 47
0

After a bit of investigation I found that whilst .Net supports a minimum date (DateTime.MinValue) of 01/01/0001 00:00:00 and a maximum (DateTime.MaxValue) of 31/12/9999 23:59:59 in SQL Server Compact Edition minimum date is 01/01/1753 00:00:00. When I entered a date greater than 01/01/1753 00:00:00, this error disappeared.

Andrei Krasutski
  • 4,913
  • 1
  • 29
  • 35
-1

Is your application or website being accessed from some third party application when this error is coming? If yes, then please check the access rights of the account which is sending the request to your application.

In our case, it was ServiceNow MID server service which was the culprit. It is a Windows service. If you want to know more about it then please read this link. So basically, you need to check two things:

  1. Under the context of which account the calling service should run to access your application?
  2. What all access rights are needed for the service's log on account to do all allowed operations in your application?

As per this article of ServiceNow we had to give Log on as a service right to the MID Server service's log on account. You can do it via in Local Security Policies console (Refer screenshot).

enter image description here

After we gave the proper access rights to the logon account, the Entity Framework issue went away. Please remember that the access rights and the log on account to be used will be specific to your application.

RBT
  • 24,161
  • 21
  • 159
  • 240
  • Please explain how this relates to a *client-side* Entity-Framework exception pertaining to a foreign key. – Gert Arnold Dec 08 '22 at 11:53
  • In our server side code, all the selects and reads were working fine via Entity Framework but updates were failing with the error that OP has posted. The error text talks about foreign key stuff as if it is totally related to database, EF, or something similar. But it is very generic in nature and can be misleading at times like it happened in our case. It can come in a number of scenrios where EF, table relationships or the DB schema is not the actual culprit. You can see in some other answers also. In our case it had to do with the user context of the calling code/third party service. – RBT Dec 09 '22 at 03:22
  • 1
    What I mean is, we can go on describing cases where this error occurs, but *nobody really explains why it happens*. All answers, including yours, are in the same line: the error occurred, I did something magically and, lo and behold, the error was gone. – Gert Arnold Dec 09 '22 at 07:47