代码第一外键关联MVC实体

时间:2014-01-12 16:46:55

标签: c# sql asp.net-mvc entity

我有一个Html清理程序(更像是一个xss检测器)我正在处理的代码,并希望记录代码xss卫生/检测过程中导致的故障。 所以在实体中,我的UserProfile有以下模型

[Table("UserProfile")]
public class UserProfile
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int UserId { get; set; }
    public string UserName { get; set; }
    public virtual List<Security> SecurityViolations { get; set; } //is this correct???
}

对于我的安全类模型,我有以下内容:

[Table("Security")]
public class Security
{
    [Key]
    public int Id { get; set; }
    [Required]
    public string SecMsg { get; set; }
    public string Trace { get; set; }
    public int ErrorCode{ get; set; }
    public int UserId { get; set; } 
    public virtual UserProfile UserProfile { get; set; } 
}

为了澄清我的想法,当安全性失败发生时,安全模型会填充信息,但我喜欢将所有信息绑定到生成错误的用户,因此我建立了外键关系(或至少尝试),到UserProfile UserId主键列。

因此,登录我的安全表的代码如下:

using (CCSecurity sec_db = new CCSecurity())
            {
                Security sec_execption = new Security();
                sec_execption.SecMsg = ex.Message;
                sec_execption.Trace = ex.StackTrace;
                sec_execption.UserId = uid;  //uid is 12, a PK entry in UserProfile
                try
                {
                    sec_db.Security.Add(sec_execption);
                    sec_db.SaveChanges();
                }
                catch (Exception e)
                {
                    Debug.WriteLine(e.StackTrace.ToString());
                }

            }

然后在我的一个单元测试执行期间,我得到以下异常:

  

“无法将属性'UserId'配置为导航属性。   该属性必须是有效的实体类型,并且该属性应具有非抽象的getter和setter。   对于集合属性,类型必须实现ICollection,其中T是有效的......“

我是实体的新手,谷歌搜索上面的许多建议并没有解决我的问题。 如何在我的Security类中引用一个外键,该外键引用我的UserProfile类中的主键并且仍然在代码中有详细记录(即ForeignKey属性字段表示Security类中的外键)?

修改

public class CCSecurity : DbContext
{
    public DbSet<Security> Security { get; set; }
    public CCSecurity()
        : base("TBCdb")
    {}
}

修改2

自动迁移生成了安全表,如下所示:

CREATE TABLE [dbo].[Security] (
[Id]        INT            IDENTITY (1, 1) NOT NULL,
[SecMsg]    NVARCHAR (MAX) NOT NULL,
[Trace]     NVARCHAR (MAX) NULL,
[ErrorCode] INT            NOT NULL,
[UserId]    INT            NOT NULL,
CONSTRAINT [PK_dbo.Security] PRIMARY KEY CLUSTERED ([Id] ASC),
CONSTRAINT [FK_dbo.Security_dbo.UserProfile_UserId] FOREIGN KEY ([UserId]) REFERENCES [dbo].[UserProfile] ([UserId]) ON DELETE CASCADE

);

似乎没问题,但它会在SaveChanges()上抛出错误:

  

“INSERT语句与FOREIGN KEY约束冲突   “FK_dbo.Security_dbo.UserProfile_UserId”。   冲突发生在数据库\“TBCdb \”,table \“dbo.UserProfile \”中,    列'UserId'。\ r \ n该语句已被终止。“

enter image description here

最新修改 所以我开始了一个新的项目控制台应用程序来测试我的主项目是否发生了奇怪的事情。我基本上在新项目中复制了我的两个模型(Security和UserProfile)并让它工作......我正在使用文件数据库而不知道我的主项目中可能出现什么问题以及可能有什么不同之处新的控制台应用项目。我在我的主项目上运行单元测试,我想知道这与它有什么关系。

谢谢!

3 个答案:

答案 0 :(得分:3)

如错误消息所示,您的外键需要与有效的实体属性相关联。因此,不是按如下方式声明外键:

[ForeignKey("UserId")]
public int? UserId { get; set; }

您需要将其声明为:

[ForeignKey("UserProfile")]
public int UserId { get; set; }

答案 1 :(得分:0)

您不需要UserId属性,只需删除它并使用UserProfile。实体框架将自动处理此问题。

sec_execption.UserProfile = getUserProfileById(uid);

getUserProfileById可能如下所示:

return sec_db.UserProfiles.Where(u => u.UserId == uid).FirstOrDefault();

P.S。

public virtual List<Security> SecurityViolations { get; set; } // is ok

public virtual ICollection<Security> SecurityViolations { get; set; } // is better

答案 2 :(得分:0)

尝试如下所示,在用户和Securtiy之间建立一对多的关系。如下所述,虚拟关键字都需要向EF指示实体之间的关系。

public class Security
{
    public int Id { get; set; }
    public string SecMsg { get; set; }
    public string Trace { get; set; }
    public int ErrorCode { get; set; }

    public int UserId { get; set; } //This is just to tell EF to name the FK column as UserId rather than UserProfile_UserId

    public virtual UserProfile UserProfile { get; set; } //This is good enough to tell EF that there is a relationship
}

public class UserProfile
{
    [Key]
    public int UserId { get; set; }
    public string UserName { get; set; }

    public virtual ICollection<Security> Securities { get; set; } //Good enough to indicate the relationship
}