使用 EF 将表单数据插入到多对多关系中的性能

本文关键字:关系 性能 EF 表单 数据 插入 使用 | 更新日期: 2023-09-27 18:37:05

我正在学习MVC和实体框架 ASP.NET。我试图创建一个带有照片和照片标签的画廊。我以某种方式实现了我的计划,但由于我还在学习,我不知道我编码的内容是否是最好的方法,因此欢迎进行更改或更正。

照片表:

        photoID
        ownerID
        Path
        imagename           

标签表:

        tagID
        tagName

照片标签表:

        phototagID
        tagID
        photoID

这是我的控制器操作中处理照片上传的示例代码:

        HttpPostedFileBase myFile = Request.Files["UploadImage"];
        //tags are comma seperated string posted using ajax
        string tagtext = Request.Form["tags"];
        // converting tags to string arrays to iterate while storing
        string[] tags = tagtext.Split(',');
        string OrgImgName = System.IO.Path.GetFileName(myFile.FileName);
        myFile.SaveAs(Path.Combine(FilePath, myFile.FileName));             
        //session userid
        var UserID = (int)Session["UserID"];
        // Saving photo to db
        photo p = new photo();
        p.ownerID = UserID;
        p.photopath = filepath;
        p.photoname = myFile.Filename;
        db.photo.add(p);
        db.savechanges();                       
        // iterating through tags to insert into database
        for (int i = 0; i < tags.Length; i++)
            {
                var tagname = tags[i].ToString();
                // checking for tag name if exists
                if (!db.tags.Any(n =>n.TagName == tagname))
                    {
                        tag t = new tag();
                        t.TagName = tags[i].ToString();
                        db.tags.Add(t);
                        db.SaveChanges();
                    }
            }
        // getting photoid of last inserted photo of user
        var photoid = (from ph in db.photos where ph.ownerID == UserID orderby ph.photoID descending select ph.photoID).FirstOrDefault();
        //iterating through tags to update many to many common table
        for (int i = 0; i < tags.Length; i++)
            {
                var tagname = tags[i].ToString();
                phototag ph = new phototag();
                ph.PhotoId = photoid;
                ph.TagId = (from t in db.tags where t.TagName == tagname select t.TagId).FirstOrDefault();
                db.phototags.Add(ph);
                db.SaveChanges();
            }

上面的代码给出了我预期的输出。现在我只测试了一次发布一张照片的单个用户;如果存在单个用户一次上传多张照片的情况,我认为它成为嵌套的循环,这在性能方面并不好,如果很多用户一次上传照片,我不知道会对代码和服务器产生什么影响。

使用 EF 将表单数据插入到多对多关系中的性能

为了帮助您更好地了解 EF 中的多对多关系的工作原理,我将向您介绍以下模型:

public class Photo
{
    public Photo()
    {
        Tags = new HashSet<Tag>();
    }
    public int PhotoId { get; set; }
    public int OwnerId { get; set; }
    public string Path { get; set; }
    public string ImageName { get; set; }
    public virtual ICollection<Tag> Tags { get; set; }   
}
public class Tag
{
    public Tag()
    {
        Photos = new HashSet<Photo>();
    }
    public int TagId { get; set; }
    public string TagName { get; set; }
    public virtual ICollection<Photo> Photos { get; set; }
}

使用此模型,不需要具有 PhotoTag 类,因为 EF 将为你创建它。EF 使用要联接的表的相应键在数据库中生成联接表。这些键既是连接表的主键,也是指向连接表的外键 此外,您可以配置该关系,如下所示:

public class YourContext : DbContext
{
    //...
    public IDbSet<Photo> Photos { get; set; }
    public IDbSet<Tag> Tags { get; set; }
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Photo>().HasMany(p => p.Tags).WithMany(c => c.Photos).Map(c=>c.ToTable("PhotoTag"));
    } 
}

现在,使用此配置,您只需要先创建照片,然后添加与之关联的标签:

 using (var db = new YourContext())
 {
    //Create the photo
     var photo = new Photo() { OwnerId = 1, ImageName = "Picture", Path = @"E:'Pictures" };
     //Add the tags
     photo.Tags.Add(new Tag() { TagName = "Family" });
     photo.Tags.Add(new Tag() { TagName = "Friend" });
     db.Photos.Add(photo);
     db.SaveChanges();
 }

您无需担心在 PhotoTag 表中填写数据,EF 将为您完成。

更新

要查找是否存在标签,您可以执行以下操作:

var tag=db.Tags.Contains(tagid);//if you have the tagid

或者,这样做:

var tag=db.Tags.FirstOrDefault(t=>t.Name==tagName);//if you have the tagName 

现在,使用该标记引用,您可以执行以下操作:

if(tag!=null)
{
  photo.Tags.Add(new Tag() { TagName = tagName });
}
else
{
  if(photo.Tags.All(t=>t.Id!=tag.Id))
     photo.Tags.Add(tag);
}