我在 EF 中有一个名为 Advertiser 的实体和另一个名为 Client 的实体。广告商有一个名为 Client 的关联字段,它是从下拉列表中选择的。我想知道如何将此关联保存到数据库。我使用的方法是找到 Client 对象(通过使用 Id),然后将此 Client 对象分配给 Advertiser.Client 导航属性。我希望通过添加这个 Advertiser 属性,我已经添加了一个与现有实体相关联的 Advertiser。然而这不是结果。相反,新的客户记录也被添加到表中。我该如何解决?
完整的解释和代码位如下......
public class Advertiser
{
public int Id { get; set; }
public string Name { get; set; }
//Navigation Properties
public virtual Client Client { get; set; }
}
还有一个叫客户端
public class Client
{
public Client()
{
Advertisers = new List<Advertiser>();
}
public int Id { get; set; }
public string Name { get; set; }
// Navigation Properties
public virtual ICollection<Advertiser> Advertisers { get; set; }
}
在单独的视图中将一堆客户端添加到数据库中。当用户登陆 Advertiser 视图时,他们有创建选项。我想要创建的是允许用户从包含所有客户端的下拉列表中选择一个客户端。我希望该广告商随后与该客户相关联。
这是控制器的代码:
//
// POST: /Advertiser/Create
[HttpPost]
public ActionResult Create(Advertiser advertiser,int Id)
{
if (ModelState.IsValid)
{
advertiser.Client = clientRepo.Retrieve(Id); // Finds and returns a Client object
System.Diagnostics.Debug.WriteLine("Saving Advertiser, with int Id = {0} and Client.Id = {1}", Id, advertiser.Client.Id);
repo.Create(advertiser);
repo.SaveChanges();
return RedirectToAction("Index");
}
return View(advertiser);
}
Advertiser 视图使用所有客户端填充下拉列表,然后返回当前选定客户端的 ID。
<div class="editor-field">
@{
var clients = new Repository<Client>().FetchAll();
var clientLists = new SelectList(clients, "Id", "Name");
}
@Html.DropDownList("Id", clientLists)
</div>
现在,这个视图正确地返回了正确的 ID。Debug.Writeline 还确认正在传回正确的 Id。问题在于之后会发生什么……
它不是插入与现有客户端实体关联的新广告商,而是首先插入广告商,然后将客户端实体的副本插入数据库。这会导致重复的客户端仅在主键 (Id) 上有所不同,
我知道这可以通过公开外键并传递外键而不是查找并将适当的客户端引用到 Advertiser.Client 属性来解决。但如果可能的话,我宁愿这样做而不暴露外键。有什么办法可以做到吗?...即我做错了什么?
如果 Repository 类中发生的事情有助于回答这个问题,我在下面添加了它:
public OperationStatus Create(TEntity item)
{
OperationStatus status = new OperationStatus {Status = true};
var value = DataContext.Set<TEntity>().Add(item);
if(value == null)
{
status = null;
}
return status;
}
public TEntity Retrieve(int id)
{
return DataContext.Set<TEntity>().Find(id);
}