Steve Randall
Steve Randall

Reputation: 521

EF Upgrade from 4.0.0 to 4.3.1 causing strange errors

I have just upgraded from EF 4.0.0 to EF 4.3.1. I am using Visual Studio 2010 Ultimate on Windows XP updated to latest release and all Windows updates/patches applied. The database engine I'm using is SQL Server 2008 R2 Developers Edition. The following code works perfectly under EF 4.0.0 but not under EF 4.3.1.

public class ItemBase
{
    public DateTime Created { get; set; }
    public int CreatedByUserID { get; set; }
    public DateTime LastModified { get; set; }
    public int LastModifiedByUserID { get; set; }

    public User CreatedBy { get; set; }
    public User LastModifiedBy { get; set; }

    public ItemBase()
    {
        CreatedByUserID = -1;
        LastModifiedByUserID = -1;
        CreatedBy = null;
        LastModifiedBy = null;
    }
}


public class User : ItemBase
{
    public int UserID { get; set; }
    public string LoginName { get; set; }
    public string Password { get; set; }
    public string EmailAddress { get; set; }
    public string Firstname { get; set; }
    public string Lastname { get; set; }
    public string DisplayName { get; set; }

    public User() : base()
    {
        UserID = -1;
        LoginName = String.Empty;
        Password = String.Empty;
        EmailAddress = String.Empty;
        Firstname = String.Empty;
        Lastname = String.Empty;
        DisplayName = String.Empty;
    }
}


protected override void OnModelCreating(System.Data.Entity.ModelConfiguration.ModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);
    modelBuilder.Entity<User>().Property(u => u.UserID).HasDatabaseGenerationOption(DatabaseGenerationOption.Identity);
}

The only thing that has changed is the version of Entity Framework I'm using. I have checked the references etc and everything is as expected.

As you can see from the code above, the User class inherits from ItemBase which in turn has a reference to a User instance. The underlying User table contains all the properties from the User class and the ItemBase class (except for the two navigation properties public User CreatedBy { get; set; } and public User LastModifiedBy { get; set; }) Running this code under 4.0.0 everything works as expected, not a single problem or issue whatsoever.

BUT, when I run the same code under 4.3.1 (without any changes whatsoever to anything else, including the database I'm using) I get the following error:

"Unable to determine the principal end of an association between the types 'User' and 'User'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations."

So I then added the following two lines to the OnModelCreating method:

modelBuilder.Entity<User>().HasRequired(u => u.CreatedBy).WithMany().HasForeignKey(k => k.CreatedByUserID);
modelBuilder.Entity<User>().HasRequired(u => u.LastModifiedBy).WithMany().HasForeignKey(k => k.LastModifiedByUserID);

I then get these strange errors:

"The provider did not return a ProviderManifestToken string."

"A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: SQL Network Interfaces, error: 26 - Error Locating Server/Instance Specified)"

I also noticed loads and loads of these errors in the output window: "A first chance exception of type 'System.Data.SqlClient.SqlException' occurred in System.Data.dll"

However, these errors appear to be a bit of a red-herring, as the database is fine, available, and the connection string is perfect too. If I subsequently undo the changes to the OnModelCreating method I get the original error again, so I don't believe the error messages I'm getting actually reflect the underlying problem that's occurring here.

So, based on all of this, I come to the following conclusions:

  1. There is a bug in version 4.3.1 of the Entity Framework?
  2. The fact that my code worked under 4.0.0 without the extra two lines in the OnModelCreating method was probably due to checks not being made in 4.0.0 which are now subsequently being made in 4.3.1?
  3. I need to add something extra to my configuration/code, or I'm missing something else to make this work again under 4.3.1?

Can anyone shed some light on this for me? Its driving me nuts! Many thanks for your time on this. Kind Regards Steve

Upvotes: 1

Views: 491

Answers (1)

Arthur Vickers
Arthur Vickers

Reputation: 7523

It looks like you have been using a pre-release version of EF 4.1. Probably CTP4 or CTP5. This is apparent because:

  • ModelBuilder was renamed to DbModelBuilder before 4.1 RTM
  • DatabaseGenerationOption was renamed to DatabaseGeneratedOption
  • The exception you are seeing was introduced before EF 4.1 was RTM'ed

Given this, I'm not 100% sure what model was being created with the pre-release version you were using. With 4.1 and above the two navigation properties are detected as inverses of each other and Code First tries to make a 1:1 relationship between User and User. Code First cannot determine the principal for this relationship so rather than guessing it throws asking you to provide it.

However, looking at your model it is clear that this is not what you want anyway. It seems much more likely that you want two 1:* uni-directional navigation props--one for CreatedBy and one for LastModifiedBy. This is what you setup in your OnModelCreating call.

With the changes made to the names of the classes to match 4.1/4.3 and with the code added to OnModelCreating, your code works fine for me on EF 4.3.1.

With regard to not being able to make the connection, you say that the connection string is correct, in which case it must be a case of EF not finding it. Assuming it is in your app.config, then you need to pass the name of it to the DbContext constructor. For example:

public class MyContext : DbContext
{
    public MyContext()
     : base("name=MyConnectionStringName")
    {
    }
}

If you're using the connection string in some other way then we'll need more details on that.

Upvotes: 2

Related Questions