使用 EF 将表单数据插入多对多关系的性能
Performance of inserting form data into many to many relationship using EF
我正在学习 ASP.NET MVC 和 Entity Framework。我试图创建一个带有照片和照片标签的画廊。我以某种方式实现了我的计划,但由于我仍在学习,我不知道我编写的代码是否是最好的方法,因此欢迎进行更改或更正。
照片table:
photoID
ownerID
Path
imagename
标签table:
tagID
tagName
phototag table:
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 中多对多关系的工作原理,我将向您推荐以下模型:
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 class,因为 EF 会为您创建它。 EF 使用它正在加入的 table 的适当键在数据库中构建一个联接 table。这些键都是连接 table 的主键和指向连接 tables 的外键此外,您可以配置该关系,如下所示:
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 中填写数据 table,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);
}
我正在学习 ASP.NET MVC 和 Entity Framework。我试图创建一个带有照片和照片标签的画廊。我以某种方式实现了我的计划,但由于我仍在学习,我不知道我编写的代码是否是最好的方法,因此欢迎进行更改或更正。
照片table:
photoID
ownerID
Path
imagename
标签table:
tagID
tagName
phototag table:
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 中多对多关系的工作原理,我将向您推荐以下模型:
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 class,因为 EF 会为您创建它。 EF 使用它正在加入的 table 的适当键在数据库中构建一个联接 table。这些键都是连接 table 的主键和指向连接 tables 的外键此外,您可以配置该关系,如下所示:
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 中填写数据 table,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);
}