Я использую codeFirst и независимые ассоциации в EF 6.1 EF не хочет обновлять отдельные объекты. Attach и StateModified не помогают связанным (FK) объектам. Добавление новых объектов и восходящих не связанных свойств работает правильно. Где проблема?EF не обновляет связанные объекты, только простые поля
У меня есть основная сущность CoachTransaction:
public class CoachTransaction : BaseEntity
{
public DateTime? TransactionDate { get; set; }
public int? Season { get; set; }
public virtual CoachPosition Position { get; set; }
public virtual Institution StartInstitution { get; set; }
public virtual Institution EndInstitution { get; set; }
}
Mapping для него:
public MapCoachTransaction()
{
ToTable("CoachTransactions");
HasKey(x => x.Id);
Property(x => x.Id).HasColumnName("TransactionId");
Property(x => x.TransactionDate);
HasOptional(x => x.Position).WithMany().Map(x => x.MapKey("CoachPositionId"));
HasOptional(x => x.StartInstitution).WithMany().Map(x => x.MapKey("StartInstitutionId"));
HasOptional(x => x.EndInstitution).WithMany().Map(x => x.MapKey("EndInstitutionId"));
}
Связанных Сущности выглядят следующим образом:
public class Institution : BaseEntity
{
public virtual InstitutionType InstitutionType { get; set; }
public string Name { get; set; }
public string ImageUrl { get; set; }
}
Mapping для родственных организаций:
public MapInstitution()
{
ToTable("Institution");
HasKey(x => x.Id);
Property(x => x.Id).HasColumnName("InstitutionId");
HasOptional(x => x.InstitutionType).WithMany(x => x.Institutions).Map(x => x.MapKey("InstitutionTypeId"));
Property(x => x.Name).HasColumnName("InstitutionName");
Property(x => x.ImageUrl).HasColumnName("InstitutionImageUrl");
}
Использование как это:
using (var context = new CoachDBContext())
{
IGenericRepository<CoachTransaction> repository = new GenericRepository<CoachTransaction>(context);
coachTransaction.Seasion = 100; // this works
coachTransaction.EndInstitution = newInstitution; this doesnt'
repository.Update(coachTransaction); // coachTransaction comes from POST to Controller
repository.Save();
}
и repository.Updarte метод использует Attach конечно:
public virtual void Update(TEntity entityToUpdate)
{
EntitySet.Attach(entityToUpdate);
dbContext.Entry(entityToUpdate).State = EntityState.Modified;
}
При этом настройки запроса SQL выглядит следующим образом:
exec sp_executesql N'UPDATE [dbo].[CoachTransactions]
SET [TransactionDate] = @0, [Season] = @1
WHERE ([TransactionId] = @2)
',N'@0 datetime2(7),@1 int,@2 int',@0='2015-04-21 20:40:38.1840996',@1=100,@2=24
Таким образом, мой объект endInstitution не обновляется.
Но если я прошу это лицо перед сохранением:
using (var context = new CoachDBContext())
{
IGenericRepository<CoachTransaction> repository = new GenericRepository<CoachTransaction>(context);
var coachTransaction = repository.GetById(coachTransaction.Id) // this fixes problem, but not acceptable in this case
coachTransaction.Season = 100;
coachTransaction.EndInstitution = newInstitution; // now this will work
repository.Update(coachTransaction); // coachTransaction comes from POST to Controller
repository.Save();
}
И SQL будет содержать ключи, относящиеся как:
exec sp_executesql N'UPDATE [dbo].[CoachTransactions]
SET [TransactionDate] = @0, [Season] = @1,
[EndInstitution] = @2
WHERE ([TransactionId] = @3)
',N'@0 datetime2(7),@1 int,@2 int, @3 int',@0='2015-04-21 20:40:38.1840996',@1=100,@2=2,@3=24
P.S.
Кроме того, использование ForeignKey Ассоциация approeach исправляет эту проблему с mappting так:
Property(x => x.PositionId).HasColumnName("CoachPositionId");
Property(x => x.StartInstitutionId).HasColumnName("StartInstitutionId");
Property(x => x.EndInstitutionId).HasColumnName("EndInstitutionId");
HasRequired(x => x.Position).WithMany().HasForeignKey(x => x.PositionId);
HasRequired(x => x.StartInstitution).WithMany().HasForeignKey(x => x.StartInstitutionId);
HasRequired(x => x.EndInstitution).WithMany().HasForeignKey(x => x.EndInstitutionId);
Но это вызывает другую проблему, когда я должен установить два свойства вместо одного, когда обновление аффилированной, как:
updatingObject.EndInstitution = existingInstitution2;
updatingObject.EndInstitutionId = existingInstitution2.Id;
INSEAD одного звонка: updatingObject.EndInstitution = existingInstitution2;
Также он требует бесполезных свойств Id. Это выглядит неправильно с моей точки зрения. Есть ли какое-то решение?
Правильно, вам нужно будет сделать SetValues для ребенка или использовать GraphDiff. http://blog.maskalik.com/entity-framework/2013/12/23/entity-framework-updating-database-from-detached-objects/ –
Но как можно создать общий репозиторий, который сохраняет и конкретизирует свойства которые необходимо обновить с помощью SetValue? –
Итак, я попробовал: updateEntity.EndInstitution = endInstitution; repository.Update (updateEntity); dbContext.Entry (updateEntity.EndInstitution) .CurrentValues.SetValues (endInstitution); Это не работает. –