How to correctly set foreign key constraint in one

2019-01-29 08:30发布

问题:

So I have one document table and ApplicationUser table. And one user can upload multiple documents and foreign key constraint has ben applied accordingly using code first approach. But the problem is I am able to save the document without assigning the UserID foreign key id in Documents table. What am I missing here. Below is my novice attempt.

ApplicationUser Model:

it's the standard model provided by the framework.

Document Model:

public class Document
{
    public int Id { get; set; }
    [StringLength(255)]
    public string FileName { get; set; }
    [StringLength(100)]
    public string ContentType { get; set; }
    public byte[] Content { get; set; }
    [StringLength(255)]
    public string DocumentName { get; set; }

    public string UserId { get; set; }
    [ForeignKey("UserId")]
    public virtual ApplicationUser User { get; set; }
} 

Post Action

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Document doc, HttpPostedFileBase uploadedresume)
{
    try
    {
        if (ModelState.IsValid)
        {
            if (uploadedresume != null && uploadedresume.ContentLength > 0)
            {
                var tempdoc = new Document
                {
                    FileName = System.IO.Path.GetFileName(uploadedresume.FileName),
                    ContentType = uploadedresume.ContentType,
                    DocumentName = doc.DocumentName
                };
                using (var reader = new System.IO.BinaryReader(uploadedresume.InputStream))
                {
                    tempdoc.Content = reader.ReadBytes(uploadedresume.ContentLength);
                }
                _context.Documents.Add(tempdoc);
            }
            // YOU CAN CLEARLY SEE I HAVE NOT SET THE tempdoc.UserId PROPERTY WITH THE LOGGED  IN USER ID
            // WHY AM I NOT GETTING ERROR HERE CONSTRAINT ERROR??
            _context.SaveChanges();
            return RedirectToAction("Create");
        }
    }
    catch (RetryLimitExceededException /* dex */){
        ModelState.AddModelError("", "");
    }
    return View("Create");
}

One to Many Migration

public override void Up()
{
    CreateTable(
        "dbo.Documents",
        c => new
            {
                Id = c.Int(nullable: false, identity: true),
                FileName = c.String(maxLength: 255),
                ContentType = c.String(maxLength: 100),
                Content = c.Binary(),
                DocumentName = c.String(maxLength: 255),
                UserId = c.String(maxLength: 128),
            })
        .PrimaryKey(t => t.Id)
        .ForeignKey("dbo.AspNetUsers", t => t.UserId)
        .Index(t => t.UserId);

}

public override void Down()
{
    DropForeignKey("dbo.Documents", "UserId", "dbo.AspNetUsers");
    DropIndex("dbo.Documents", new[] { "UserId" });
    DropTable("dbo.Documents");
}
}

Entry in Documents table:

Expected Behaviour

If I have set up FK constraint properly then I shold have seen the constraint error when saving in database. It should not have allowed NULL values because it is not a valid userId that is there in ApplicationUserId Table.

Or nullable foreign key is the expected behaviour??

回答1:

Maybe you can configure this in the function onModelCreating into your context file, something like this:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {

        modelBuilder.Entity<ApplicationUser>()
            .HasMany(u => u.Documents)
            .WithRequired(d => d.UserId)
            .WillCascadeOnDelete(false);

        base.OnModelCreating(modelBuilder);
    }

You will have to create a property in your ApplicationUser class to reference the documents like this:

public ICollection<Document> Documents { get; set; }


回答2:

This happens because you have a relation but this is optional, may be one or none, you have to put this field as a required if you need to make this relation mandatory:

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