[英]Many to Many Relation - Entity Framework
我正在與多對多關系進行工作,基本上是:
+-------------+ +-----------------+ +---------------------------+
| Redes | | Objetivos | | RedesObjetivos |
+-------------+ +-----------------+ +---------------------------+
| | RedesID | | | ObjetivosID | | | RedesID | ObjetivosID |
+---+---------+ +-----------------+ +---------------------------+
| 1 | | | 1 | | | 1 | | |
+---+---------+ +-----------------+ +---------------------------+
表Objetivos是一組先前注冊的選項。 當我的用戶嘗試注冊新的Redes時,他在Objetivos列表中進行選擇並保存。
目前,Objetivos表有8個選項
+------------------+
| Objetivos |
+------------------+
| | ObjetivosID |
+----+-------------+
| 1 | 1 |
+----+-------------+
| 2 | 2 |
+----+-------------+
| 3 | 3 |
+----+-------------+
| 4 | 4 |
+----+-------------+
| 5 | 5 |
+----+-------------+
| 6 | 6 |
+----+-------------+
| 7 | 7 |
+----+-------------+
| 8 | 8 |
+----+-------------+
假設我包括一個新的Redes並選擇Objetivos 5至8,當前的最終結果是:
+-------------+ +-------------------+ +---------------------------+
| Redes | | Objetivos | | RedesObjetivos |
+-------------+ +-------------------+ +---------------------------+
| | RedesID | | | ObjetivosID | | | RedesID | ObjetivosID |
+---+---------+ +---+---------------+ +---------------------------+
| 1 | 1 | | 1 | 1 | | 1 | 1 | 9 |
+---+---------+ +---+---------------+ +---------------------------+
| 2 | 2 | | 2 | 1 | 10 |
+---+---------------+ +---------------------------+
| 3 | 3 | | 3 | 1 | 11 |
+---+---------------+ +---------------------------+
| 4 | 4 | | 4 | 1 | 12 |
+---+---------------+ +---------------------------+
| 5 | 5 |
+---+---------------+
| 6 | 6 |
+---+---------------+
| 7 | 7 |
+---+---------------+
| 8 | 8 |
+---+---------------+
| 9 | 9 |
+---+---------------+
| 10| 10 |
+---+---------------+
| 11| 11 |
+---+---------------+
| 12| 12 |
+---+---------------+
我想要的結果是:
+-------------+ +-------------------+ +---------------------------+
| Redes | | Objetivos | | RedesObjetivos |
+-------------+ +-------------------+ +---------------------------+
| | RedesID | | | ObjetivosID | | | RedesID | ObjetivosID |
+---+---------+ +---+---------------+ +---------------------------+
| 1 | 1 | | 1 | 1 | | 1 | 1 | 5 |
+---+---------+ +---+---------------+ +---------------------------+
| 2 | 2 | | 2 | 1 | 6 |
+---+---------------+ +---------------------------+
| 3 | 3 | | 3 | 1 | 7 |
+---+---------------+ +---------------------------+
| 4 | 4 | | 4 | 1 | 8 |
+---+---------------+ +---------------------------+
| 5 | 5 |
+---+---------------+
| 6 | 6 |
+---+---------------+
| 7 | 7 |
+---+---------------+
| 8 | 8 |
+---+---------------+
基本上,EF不會識別Objetivos是否已存在於數據庫中並正在創建新行。 我如何正確地向EF指示那些Objetivos已經存在?
我進行了很多搜索,以了解如何與EF進行多對多協作,我知道有些問題與我的相似,但是由於無法解決它們的問題,我決定按順序發布整個方案獲得幫助。
這是我目前所擁有的:
//DAL Layer
//Interface where a set the basic database methods
public interface IDao<T> where T : class
{
//Save
int Salva(T Modelo);
//Update
int Atualiza(T model);
//Delete
void Exclui(T model);
//GetAll
IEnumerable<T> ObtemTodos();
//GetByID
T ObtemPorId(object id);
IEnumerable<T> Where(Expression<Func<T, bool>> expression);
IEnumerable<T> OrderBy(Expression<System.Func<T, bool>> expression);
}
//Generic context, where i implement the methods in the interface
public partial class dbContext<T> : DbContext where T : class
{
public DbSet<T> DbSet
{
get;
set;
}
public dbContext()
: base("name=dbContext")
{
}
public virtual void ChangeObjectState(object model, EntityState state)
{
((IObjectContextAdapter)this)
.ObjectContext
.ObjectStateManager
.ChangeObjectState(model, state);
}
//Save
public virtual int Salva(T model)
{
this.DbSet.Add(model);
return this.SaveChanges();
}
//Update
public virtual int Atualiza(T model)
{
var entry = this.Entry(model);
if (entry.State == EntityState.Detached)
this.DbSet.Attach(model);
this.ChangeObjectState(model, EntityState.Modified);
return this.SaveChanges();
}
//Delete
public virtual void Exclui(T model)
{
var entry = this.Entry(model);
if (entry.State == EntityState.Detached)
this.DbSet.Attach(model);
this.ChangeObjectState(model, EntityState.Deleted);
this.SaveChanges();
}
//GetAll
public virtual IEnumerable<T> ObtemTodos()
{
return this.DbSet.ToList();
}
//GetByID
public virtual T ObtemPorId(object id)
{
return this.DbSet.Find(id);
}
public virtual IEnumerable<T> Where(Expression<Func<T, bool>> expression)
{
return this.DbSet.Where(expression);
}
public IEnumerable<T> OrderBy(Expression<Func<T, bool>> expression)
{
return this.DbSet.OrderBy(expression);
}
}
//Then the relevant DAO classes where I implement specific database methods if necessary
public class RedesDAO : dbContext<Redes>, IDao<Redes>
{
//Save
public override int Salva(Redes Model)
{
ObjetivosDAO ObjetivosDAO = new ObjetivosDAO();
Model.RedeObjetivos = new List<Objetivos>();
//ObjetivosSelecionados is a List<int> with Ids that relates to user's selected options on my view
//each option relates to an especific Objetivos row that already exist in the database
foreach (int ObjetivoID in Model.ObjetivosSelecionados)
{
//So, with each ID I obtain the whole information for that entity
//by using the ObtemPorId = GetByID method and adding it to models' collection
Objetivos Objetivo = ObjetivosDAO.ObtemPorId(ObjetivoID);
Model.RedeObjetivos.Add(Objetivo);
}
this.DbSet.Add(Model);
return this.SaveChanges();
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Redes>().
HasMany(c => c.RedeObjetivos).
WithMany(p => p.Redes).
Map(
m =>
{
m.MapLeftKey("RedeID");
m.MapRightKey("ObjetivoID");
m.ToTable("RedesObjetivos");
});
}
}
public class ObjetivosDAO : dbContext<Objetivos>, IDao<Objetivos>
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Objetivos>().
HasMany(c => c.Redes).
WithMany(p => p.RedeObjetivos).
Map(
m =>
{
m.MapLeftKey("ObjetivoID");
m.MapRightKey("RedeID");
m.ToTable("RedesObjetivos");
});
}
}
//And my models/tables
public partial class Redes
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int RedeID { get; set; }
[Required]
public ICollection<Objetivos> RedeObjetivos { get; set; }
[NotMapped]
public List<int> ObjetivosSelecionados { get; set; }
}
public partial class Objetivos
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ObjetivoID { get; set; }
[Required]
public ICollection<Redes> Redes { get; set; }
}
請注意,為了保存新的Redes而執行的方法是RedesDAO類上的重寫。
//Model = Information that comes from my view
public override int Salva(Redes Model)
您指定兩個不同的DbContext, RedesDAO
和ObjetivosDAO
。 兩個對象的EntityFramework上下文是不同的,這意味着您的第二個上下文無法看到該對象是從數據庫中獲取的。
要修復,可以替換以下行:
Objetivos Objetivo = ObjetivosDAO.ObtemPorId(ObjetivoID);
與:
Objetivos Objetivo = base.Set<Objetivos>().Find(ObjetivoID);
這樣可以防止將對象誤認為是新對象。
附帶說明一下,除非有特定的原因將它們分開,否則最好使用單個DbContext類與數據庫進行通信。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.