简体   繁体   中英

Adding New Entity with New Navigation Property Using Entity Framework

I have a class model allows me to add a feature Image to a ProductType entity. The individual ProductType class definition identifies a HomePageImageId and HomePageImage navigation property which references a specific Image.

I have an Image class definition which contains all the META information for an image (ie width, height, format type, name, etc.).

I also have an ImageData class definition which contains the actual image data. This possesses a FK relationship to it's meta information available via the aforementioned Image class.

So here's what the EF Entities look like.

[DataContract]
[Table("ProductTypes")]
public class ProductType : IEntity
{
    [Key]
    [DataMember]
    [Column("Id")]
    public Int64 Id { get; set; }

    [DataMember]
    [DataType(DataType.Text)]
    [Column("Name")]
    public String Name { get; set; }

    [DataMember]
    [DataType(DataType.MultilineText)]
    [Column("Description")]
    public String Description { get; set; }

    [DataMember]
    [DataType(DataType.MultilineText)]
    [Column("Excerpt")]
    public String Excerpt { get; set; }

    [DataMember]
    [Column("ImageId")]
    public Int64? ImageId { get; set; }

    [ForeignKey("ImageId")]
    public virtual Image HomePageImage { get; set; }

}


[DataContract]
[Table("Images")]
public class Image : IEntity
{
    [Key]
    [DataMember]
    [Column("Id")]
    public Int64 Id { get; set; }

    [DataMember]
    [Column("Name")]
    [DataType(DataType.Text)]
    public String Name { get; set; }

    // Addt'l properties removed 

    [DataMember]
    [Column("DataId")]
    public Int64 DataId { get; set; }


    #region Navigation Properties

    [ForeignKey("DataId")]
    public virtual ImageData ImageData { get; set; }

    #endregion

}


[DataContract]
[Table("ImageData")]
public class ImageData : IEntity
{
    [Key, ForeignKey("Image")]
    [DataMember]
    [Column("Id")]
    public Int64 Id { get; set; }

    [Column("Data")]
    [MaxLength]
    [DataType(DataType.Upload)]
    public byte[] Data { get; set; }

    public virtual Image Image { get; set; } 

}

Structurally this all looks good. The problem is that when I want to ADD a new image I am getting the following error.

A foreign key value cannot be inserted because a corresponding primary key value does not exist. [ Foreign key constraint name = ImageData ]

I understand the error. I am just not sure why it's occurring. The AddImage method in the repository looks like the following code snippet where the "image" parameter contains not only the Image meta data, but its ImageData property which has been successfully populated with an instance of ImageData containing the byte[] information for an image. Each entity is new and have Id's of 0.

    public static Image AddImage(Image image)
    {
        Image ret = null;
        using(Context ctx = new Context())
        {
            Image ret = ctx.Images.Add(image);
            ctx.SaveChanges();
        }
        return ret;
    }

I would have expected that since an instance of ImageData has been assigned to the Navigation property that the ADD would manage the relationships between the two, inserting them and updating the Keys as neeccessary. At least that's how I have seen it work in the past.

It's close to this post but where he is referring to an existing entity I am looking to create both as new entities.

Can anyone see what I am missing here?

UPDATE 11/05/2013

I have condensed the code to fewer lines to hopefully narrow the spotlight on the issue ... I am still receiving the error.

        using (Context ctx = new Context())
        {
            //
            // Initialize a ProductType instance.
            ProductType productType = ProductRepository2.GetProductType(ctx, productTypeId);
            productType.Description = txtDescription.Text.Trim();
            productType.Excerpt = txtDescription.Text.Substring(0, (txtDescription.Text.Trim().Length < 100) ? txtDescription.Text.Trim().Length : 100);

            //
            // If an image was uploaded then initialize the Image DTOs
            if (fileUpload.FileBytes.Length > 0)
            {
                ImageData imgData = new ImageData { Data = fileUpload.FileBytes };
                productType.HomePageImage = Infrastructure.Utils.ImageUtils.GetPostedImage(fileUpload.PostedFile);
                productType.HomePageImage.ImageData   = imgData;   
                productType.HomePageImage.DateAdded   = DateTime.Now;
                productType.HomePageImage.DateUpdated = DateTime.Now;
            }
            ctx.SaveChanges();
        }

You might need to try using an Association rather than a ForeignKey reference:

[Association("FK_MyName", "ImageId", "ImageId")]

I've used this in the past to create custom entities for RIA Services

What I do here is I create a ProductTpe object and assign Image object to HomePageImage property in ProductType object and when I add ProductType object to ProductTypes in context and call saveChanges() method, It will create ImageData, Image and ProductType in DB.

ProductType prodObj = new ProductType
{
    Name="name",
    Description= "description",
    Excerpt ="excerpt",
    Image= new Image //you can directly assign your image object here
    {
        Name="name",
        ImageData=new ImageData
        {
            Data=new byte[0]; //use your data
        }
    }
};

using(Context ctx = new Context())
{
    ctx.ProductTypes.add(prodObj);
    ctx.saveChanges();
    return prodObj;
}

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