简体   繁体   中英

Foreign Key Issue preventing me from tying an existing table into ASP.NET Identity 2.0 (Azure Servers)

Original error is now resolved, though I'm not any closer to attaining the desired functionality. See final update

The First section of this is my original question posted on Reddit (/sql, and /csharp) last week. At the bottom is some updated information since then

I'm working on a webapp (C#, MVC 5) that uses an Azure SQL database. I'm also implementing the built in ASP.NET Identity 2.0 system (and I'm sure that's where my issue is).

Probably because of a setting i chose, the credential system insisted on using a local db, rather than my cloud based db (which is fairly useless once my laptop is turned off).

I've migrated all the tables to my azure sql db, set up a new connection string and pointed the IdentityModel at the new connection, rather than the default (and yes, it is a different connection than the regular azure connection which uses entity framework rather than SqlClient)

When I try to register against the local database, everything works perfectly. When I change it to reference the azure database, I get this error:

 SqlException (0x80131904): The INSERT statement conflicted with the FOREIGN KEY constraint "FK_AspNetUsers_ToTable". The conflict occurred in database "PhoenixMachineTracking", table "dbo.Distributor", column 'Dist_ID'. The statement has been terminated. 

This is where the error is occurring:

 Line 153:            {
 Line 154:                var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
 **Line 155:                var result = await UserManager.CreateAsync(user, model.Password);**
 Line 156:                if (result.Succeeded)
 Line 157:                {

I've changed a few things with little success (though this is the newest error; i'm making progress lol) and i'm not sure at this point if the issue is within my connection string (i don't think so) almost certainly not - see updates at the end, my c# code (I can't find anything that looks wrong) or my tables (it looks like all of my foreign keys are present and correct)

What am I doing wrong? Below are the table creation scripts, as well as my "classes" (not sure if that's what they're called when VS builds them for you from a database)

Distributor Table (users that will be logging in)

 CREATE TABLE [dbo].[Distributor] (  
[Dist_ID]      NVARCHAR (128) NOT NULL,  
[Dist_Name]    NVARCHAR (256) NULL,  
[Dist_Address] VARCHAR (50)   NULL,  
[Dist_City]    VARCHAR (50)   NULL,  
[Dist_State]   VARCHAR (50)   NULL,  
[Dist_Zip]     VARCHAR (50)   NULL,  
[Dist_Phone]   VARCHAR (50)   NULL,  
[Dist_Fax]     VARCHAR (50)   NULL,  
[Dist_Contact] VARCHAR (50)   NULL,  
[Dist_Email]   VARCHAR (50)   NULL,  
CONSTRAINT [PK_dbo.Distributor] PRIMARY KEY CLUSTERED ([Dist_ID] ASC));

ASP.NET Table generated by visual studio as part of ASP Identity

 CREATE TABLE [dbo].[AspNetUsers] (
[Id]                   NVARCHAR (128) NOT NULL,
[Email]                NVARCHAR (256) NULL,
[EmailConfirmed]       BIT            NOT NULL,
[PasswordHash]         NVARCHAR (MAX) NULL,
[SecurityStamp]        NVARCHAR (MAX) NULL,
[PhoneNumber]          NVARCHAR (MAX) NULL,
[PhoneNumberConfirmed] BIT            NOT NULL,
[TwoFactorEnabled]     BIT            NOT NULL,
[LockoutEndDateUtc]    DATETIME       NULL,
[LockoutEnabled]       BIT            NOT NULL,
[AccessFailedCount]    INT            NOT NULL,
[UserName]             NVARCHAR (256) NOT NULL,
CONSTRAINT [PK_dbo.AspNetUsers] PRIMARY KEY CLUSTERED ([Id] ASC),
CONSTRAINT [FK_AspNetUsers_ToTable] FOREIGN KEY ([Id]) REFERENCES [dbo].[Distributor] ([Dist_ID]));


 GO
 CREATE UNIQUE NONCLUSTERED INDEX [UserNameIndex]
ON [dbo].[AspNetUsers]([UserName] ASC);

ASP.NET Users Class - generated as part of ASP.NET Identity

namespace PhoenixProductTracking.db
 {
using System;
using System.Collections.Generic;

public partial class AspNetUsers
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public AspNetUsers()
    {
        this.AspNetUserClaims = new HashSet<AspNetUserClaims>();
        this.AspNetUserLogins = new HashSet<AspNetUserLogins>();
        this.AspNetRoles = new HashSet<AspNetRoles>();

    }

    public string Id { get; set; }
    public string Email { get; set; }
    public bool EmailConfirmed { get; set; }
    public string PasswordHash { get; set; }
    public string SecurityStamp { get; set; }
    public string PhoneNumber { get; set; }
    public bool PhoneNumberConfirmed { get; set; }
    public bool TwoFactorEnabled { get; set; }
    public Nullable<System.DateTime> LockoutEndDateUtc { get; set; }
    public bool LockoutEnabled { get; set; }
    public int AccessFailedCount { get; set; }
    public string UserName { get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<AspNetUserClaims> AspNetUserClaims { get; set; }
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<AspNetUserLogins> AspNetUserLogins { get; set; }
    public virtual Distributor Distributor { get; set; }
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<AspNetRoles> AspNetRoles { get; set; }

}}

Distributor class - generated from database

 namespace PhoenixProductTracking.db
 {
using System;
using System.Collections.Generic;

public partial class Distributor
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public Distributor()
    {
        this.Machine = new HashSet<Machine>();
    }

    public string Dist_ID { get; set; }
    public string Dist_Name { get; set; }
    public string Dist_Address { get; set; }
    public string Dist_City { get; set; }
    public string Dist_State { get; set; }
    public string Dist_Zip { get; set; }
    public string Dist_Phone { get; set; }
    public string Dist_Fax { get; set; }
    public string Dist_Contact { get; set; }
    public string Dist_Email { get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<Machine> Machine { get; set; }
    public virtual AspNetUsers AspNetUsers { get; set; }
}}

Identity Model Class (where the default connection is changed)

 namespace PhoenixProductTracking.Models
 {
// You can add profile data for the user by adding more properties to your ApplicationUser class, please visit http://go.microsoft.com/fwlink/?LinkID=317594 to learn more.
public class ApplicationUser : IdentityUser
{
    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
    {
        // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
        var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
        // Add custom user claims here
        return userIdentity;
    }
}

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext()
        : base("PhoenixLogInConnection", throwIfV1Schema: false)
    {             **THIS IS WHERE THE CONNECTION WAS CHANGED FROM "DEFAULTCONNECTION"**
    }

    public static ApplicationDbContext Create()
    {
        return new ApplicationDbContext();
    }
}}

Web.Config - where my connection strings are defined

Default (local) connection

  <add name="DefaultConnection" connectionString="Data Source=(LocalDb)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\aspnet-PhoenixProductTracking-20160118123425.mdf;Initial Catalog=aspnet-PhoenixProductTracking-20160118123425;Integrated Security=True" providerName="System.Data.SqlClient" />

Azure Connection for Entities

<add name="PhoenixMachineTrackingEntities" connectionString="metadata=res://*/db.PhoenixAzureDb.csdl|res://*/db.PhoenixAzureDb.ssdl|res://*/db.PhoenixAzureDb.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=*****.database.windows.net;initial catalog=PhoenixMachineTracking;persist security info=True;user id=******4;password=*****;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />

Azure connection for Log-In

<add name="PhoenixLogInConnection" connectionString="Server=******.database.windows.net,1433;Database=PhoenixMachineTracking;User ID=*****;Password=******;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;" providerName="System.Data.SqlClient"/>

UPDATED:

Since that was posted I've tried a few things, with middling success. I can confirm that when I unhook the AspNetUsers table from the Distributor table, the "register" functions works (this is the built in register function that is seen on the first page of any new MVC project. I've only altered the first page to show the data I want [for the time being] as I need to get the log-in system working before I can go any further). Once I hook them together it stops working. This is still using the Azure connection string, rather than the DefaultConnection, meaning I can exclude the connection as an issue.

I have tried manually putting a distributor into the distributor table and then registering against that user name to eliminate the possibility of the issue coming from the data not being present in the distributor table when the AspNetUser table tries to foreign key to it. I get the same error when I do this.

The models and "classes" (automatically created by visual studio from my existing database structure. It shows up under the edmx in my solution explorer, but they may not actually be called classes...i'm a little inexperienced here) all look correct, even containing (what i think are) proper references to whichever tables/classes they relate to.

I'm currently digging down into the ASP.NET Identity files trying to understand how it's communicating with the database. Hopefully this can show me my issue. Minimal luck at the moment on that. I'm also experimenting to see if I can create the relationship on the edmx diagram and then use that to update the table so that it creates the relationship itself (removing an error stemming from my lack of experience)

I wouldn't say i'm in over my head, but i'm certainly up to my eyeballs, and I cold use some help. I'll keep researching (im not the sort of person to sit and wait for an answer) and update if I figure it out, but it's been a few days now and I need to solve this so I can continue working through the project (single, just-graduated developer at a small business, so my support network is rather limited)

Thanks in advance for any help

UPDATE 2:

Thanks to NPC. (s)He pointed out that I was associating two primary keys, an unusual method, and that that may be causing an issue. I created a field in my Distributor table called "AspNetUserID" and associated that with the ID field from AspNetUsers and this has cleared up the error for me.

At this point, I need to figure out where how to automatically create that association in the code (currently copy-paste), either by creating the needed distributor, or associating with an existing distributor. If someone would like to point me in the direction of where this occurs in the code, that'd be helpful. Otherwise I'll just stumble around until I find it

You need to remove the AspNetUsers partial class. I assume you used some kind of reverse engineering to create your models from the DB. Once you have declared the ApplicationUser : IdentityUser and tied them to your context by ApplicationDbContext : IdentityDbContext<ApplicationUser> there is no need for the identity classes (AspNetUsers, AspNetRoles...). it is taken care by Identity EntityFramwork. Any Additional properties you want to add to your user should be added to ApplicationUser class.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM