我有两个具有多对多关系的实体,如下所示。
public class StandardContact {
...
public virtual ICollection<RelayConfig> RelayConfigs { get; set; }
}
public class RelayConfig {
....
public virtual ICollection<StandardContact> StandardContacts { get; set; }
}
我正在尝试更新 RelayConfig 及其与 StandardContact 的关系。这是我在 Update() 方法中添加的代码。它只是添加一些新的 StandardContact 和/或删除现有的 StandardContacts(根据用户的要求)。参数exposedContacts表示应在数据库中更新的StandardContacts的全包列表
public void Update(RelayConfig relayConfig, List<StandardContact> exposedContacts) {
RelayConfig dbRelayConfig = context.RelayConfigs.Include(r => r.StandardContacts)
.Where(r => r.Id == relayConfig.Id).SingleOrDefault();
context.Entry<RelayConfig> (dbRelayConfig).CurrentValues.SetValues(relayConfig);
List<StandardContact> addedExposedContacts =
exposedContacts.Where(c1 => !dbRelayConfig.StandardContacts.Any(c2 => c1.Id == c2.Id)).ToList();
List<StandardContact> deletedExposedContacts =
dbRelayConfig.StandardContacts.Where(c1 => !exposedContacts.Any(c2 => c2.Id == c1.Id)).ToList();
StandardContact dbExposedContact = null;
addedExposedContacts.ForEach(exposedContact => {
dbExposedContact = context.StandardContacts.SingleOrDefault(sc => sc.Id == exposedContact.Id);
dbRelayConfig.StandardContacts.Add(dbExposedContact);
});
deletedExposedContacts.ForEach(exposedContact => { dbRelayConfig.StandardContacts.Remove(exposedContact); });
}
与 RelayConfig 相关的新 StandardContact 实体的添加正在正确进行。但是,删除(上面代码中的最后一行)没有任何效果,链接表中的多对多关系保持不变。
简而言之,我无法从 RelayConfig 对象中删除 StandardContact 实体。我没有得到任何异常,但代码运行通过。
更新:
这是与数据库相关的代码:
RelayContext 类
public class RelayContext : DbContext {
public DbSet<Station> Stations { get; set; }
public DbSet<StandardContact> StandardContacts { get; set; }
public DbSet<RelayConfig> RelayConfigs { get; set; }
public DbSet<StandardRelay> StandardRelays { get; set; }
public DbSet<Rack> Racks { get; set; }
public DbSet<Group> Groups { get; set; }
public DbSet<Relay> Relays { get; set; }
public DbSet<Contact> Contacts { get; set; }
public RelayContext() {
Database.SetInitializer(new RelayContextInitializer());
}
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
modelBuilder.Entity<Rack>().HasOptional<RelayConfig>(r => r.DefaultFirstRelayConfig).WithMany(rc => rc.RacksWithDefaultFirstRelay).WillCascadeOnDelete(false);
modelBuilder.Entity<Rack>().HasOptional<RelayConfig>(r => r.DefaultSecondRelayConfig).WithMany(rc => rc.RacksWithDefaultSecondRelay).WillCascadeOnDelete(false);
}
}
RelayConfig 存储库
public class RelayConfigRepository {
internal RelayContext context;
public RelayConfigRepository(RelayContext context) {
this.context = context;
}
....
public void Update(RelayConfig relayConfig, List<StandardContact> exposedContacts) {
RelayConfig dbRelayConfig = context.RelayConfigs.Include(r => r.StandardContacts)
.Where(r => r.Id == relayConfig.Id).SingleOrDefault();
context.Entry<RelayConfig> (dbRelayConfig).CurrentValues.SetValues(relayConfig);
List<StandardContact> addedExposedContacts =
exposedContacts.Where(c1 => !dbRelayConfig.StandardContacts.Any(c2 => c1.Id == c2.Id)).ToList();
List<StandardContact> deletedExposedContacts =
dbRelayConfig.StandardContacts.Where(c1 => !exposedContacts.Any(c2 => c2.Id == c1.Id)).ToList();
StandardContact dbExposedContact = null;
addedExposedContacts.ForEach(exposedContact => {
dbExposedContact = context.StandardContacts.SingleOrDefault(sc => sc.Id == exposedContact.Id);
dbRelayConfig.StandardContacts.Add(dbExposedContact);
});
deletedExposedContacts.ForEach(exposedContact => { dbRelayConfig.StandardContacts.Remove(exposedContact);});
}
....
}
UnitOfWork 类
public class UnitOfWork : IDisposable {
private RelayContext context = new RelayContext();
private bool disposed = false;
private RelayConfigRepository _relayConfigRepository;
public RelayConfigRepository RelayConfigRepository {
get {
if (_relayConfigRepository == null) {
_relayConfigRepository = new RelayConfigRepository(context);
}
return _relayConfigRepository;
}
}
private StandardContactRepository _standardContactRepository;
public StandardContactRepository StandardContactRepository {
get {
if (_standardContactRepository == null) {
_standardContactRepository = new StandardContactRepository(context);
}
return _standardContactRepository;
}
}
public void Save() {
try {
context.SaveChanges();
}
catch (DbUpdateConcurrencyException ex) {
throw new RepositoryException(ErrorMessages.UpdateConcurrencyError);
}
catch (Exception ex) {
throw new RepositoryException(ErrorMessages.GeneralError);
}
}
protected virtual void Dispose(bool disposing) {
if (!this.disposed) {
if (disposing) {
context.Dispose();
}
}
this.disposed = true;
}
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
}
调用 RelayConfigRepository 上的 Update 方法的WPF 客户端(ViewModel) 。
[Export(typeof(RelayConfigEditViewModel))]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class RelayConfigEditViewModel :Screen {
private RelayConfig _relayConfig;
public RelayConfig RelayConfig {
get { return _relayConfig; }
set { _relayConfig = value; NotifyOfPropertyChange(() => RelayConfig); }
}
private ObservableCollection<StandardContact> _standardContacts = new ObservableCollection<StandardContact>();
public ObservableCollection<StandardContact> StandardContacts {
get { return _standardContacts;}
set { _standardContacts = value; NotifyOfPropertyChange(() => StandardContacts); }
}
....
public void Save() {
List<StandardContact> exposedContacts = StandardContacts.Where(sc => sc.IsMarked).ToList();
try {
using (UnitOfWork unitOfWork = new UnitOfWork()) {
if (editMode == EditMode.Add) {
unitOfWork.RelayConfigRepository.Insert(RelayConfig, exposedContacts);
}
else {
unitOfWork.RelayConfigRepository.Update(RelayConfig, exposedContacts);
}
unitOfWork.Save();
}
}
catch (Exception ex) {
HandleException(ex);
}
events.Publish(RelayConfig);
}
}
更新 2
跟踪有点笨拙,但我可以看到与更新方法相关的特殊过程语句。以下是 EF 生成的相关 SQL 语句。
update [dbo].[RelayConfigs]
set [Name] = @0, [DisplayName] = @1
where (([Id] = @2) and ([Version] = @3))
**exec sp_executesql N'insert [dbo].[RelayConfigStandardContacts]([RelayConfig_Id], [StandardContact_Id])
values (@0, @1)
',N'@0 int,@1 int',@0=1,@1=4**
如您所见,有用于更新 RelayConfig 记录和在链接表 RelayConfigStandardContact 中添加另一个条目的 SQL(我在多对多记录中添加的新记录)。但是没有为我从多对多关系中删除的链接表记录生成 SQL 语句。