(EF4.1 - 4.0框架)實體框架DBContext全局緩存?
Web上的大多數代碼示例都指示了實體框架的最佳實踐;他們說你在一個使用塊中包裝你的DBContext的用法,以確保無狀態操作。即使如此,我得到了似乎是共享緩存錯誤。
ERROR
具有相同鍵的對象已經存在於ObjectStateManager。 ObjectStateManager無法使用相同的 鍵追蹤多個對象。
環顧四周,當有人在許多調用中共享一個DBContext的全局實例時,會發生這種情況。
但是,我在第二次調用下面的函數時收到了這個問題,它位於靜態數據訪問層服務類中。
public static void UpdateRollout(Rollout rollout)
{
using (ITAMEFContext db = new ITAMEFContext(ConnectionStrings.XYZConnectionString))
{
db.Configuration.ProxyCreationEnabled = false;
db.Configuration.LazyLoadingEnabled = false;
FixUp(rollout);
db.Rollouts.Attach(rollout);
db.Entry(rollout).State = System.Data.EntityState.Modified;
db.SaveChanges();
//db.Entry(rollout).State = System.Data.EntityState.Detached;
}
}
private static void FixUp(Rollout rollout)
{
// ensure manual fixup of foreign keys
if (rollout.RolloutState != null)
rollout.FK_RolloutState_ID = rollout.RolloutState.ID;
if (rollout.Lead != null)
rollout.RolloutLead_FK_User_ID = rollout.Lead.ID;
}
EFContext是通過引用edmx模型的EF 4.x DBContext Fluent Generator生成的。
看起來是這樣。
public partial class ITAMEFContext : DbContext
{
static ITAMEFContext()
{
Database.SetInitializer<ITAMEFContext>(null);
}
public ITAMEFContext() : base("name=ITAMEFContext")
{
this.Configuration.LazyLoadingEnabled = false;
}
public ITAMEFContext(string nameOrConnectionString) : base(nameOrConnectionString)
{
}
public ITAMEFContext(string nameOrConnectionString, DbCompiledModel model) : base(nameOrConnectionString, model)
{
}
public ITAMEFContext(DbConnection existingConnection, bool contextOwnsConnection) : base(existingConnection, contextOwnsConnection)
{
}
public ITAMEFContext(DbConnection existingConnection, DbCompiledModel model, bool contextOwnsConnection) : base(existingConnection, model, contextOwnsConnection)
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<IncludeMetadataConvention>();
modelBuilder.Configurations.Add(new Asset_Mapping());
modelBuilder.Configurations.Add(new AssetAllocation_Mapping());
modelBuilder.Configurations.Add(new AssetAssignee_Mapping());
modelBuilder.Configurations.Add(new AssetAssigneeType_Mapping());
modelBuilder.Configurations.Add(new AssetDeAllocation_Mapping());
modelBuilder.Configurations.Add(new AssetState_Mapping());
modelBuilder.Configurations.Add(new AssetType_Mapping());
modelBuilder.Configurations.Add(new Department_Mapping());
modelBuilder.Configurations.Add(new Location_Mapping());
modelBuilder.Configurations.Add(new ManagementGroup_Mapping());
modelBuilder.Configurations.Add(new Role_Mapping());
modelBuilder.Configurations.Add(new Rollout_Mapping());
modelBuilder.Configurations.Add(new RolloutState_Mapping());
modelBuilder.Configurations.Add(new ServiceArea_Mapping());
modelBuilder.Configurations.Add(new Software_Mapping());
modelBuilder.Configurations.Add(new SoftwareType_Mapping());
modelBuilder.Configurations.Add(new SubTeam_Mapping());
modelBuilder.Configurations.Add(new sys_UserLock_Mapping());
modelBuilder.Configurations.Add(new Team_Mapping());
modelBuilder.Configurations.Add(new User_Mapping());
modelBuilder.Configurations.Add(new WorkingMethod_Mapping());
}
public DbSet<Asset> Assets { get; set; }
public DbSet<AssetAllocation> AssetAllocations { get; set; }
public DbSet<AssetAssignee> AssetAssignees { get; set; }
public DbSet<AssetAssigneeType> AssetAssigneeTypes { get; set; }
public DbSet<AssetDeAllocation> AssetDeAllocations { get; set; }
public DbSet<AssetState> AssetStates { get; set; }
public DbSet<AssetType> AssetTypes { get; set; }
public DbSet<Location> Locations { get; set; }
public DbSet<Department> Departments { get; set; }
public DbSet<ManagementGroup> ManagementGroup { get; set; }
public DbSet<Role> Roles { get; set; }
public DbSet<ServiceArea> ServiceAreas { get; set; }
public DbSet<SubTeam> SubTeams { get; set; }
public DbSet<Team> Teams { get; set; }
public DbSet<User> User { get; set; }
public DbSet<WorkingMethod> WorkingMethods { get; set; }
public DbSet<Rollout> Rollouts { get; set; }
public DbSet<RolloutState> RolloutStates { get; set; }
public DbSet<Software> Softwares { get; set; }
public DbSet<SoftwareType> SoftwareTypes { get; set; }
public DbSet<sys_UserLock> sys_UserLock { get; set; }
}
我希望能夠根據需要多次從我的BL層調用UpdateRollout。 UI將需要保持作爲先前提取列表的一部分返回的POCO卷展欄實體圖形。
部署和所有其他實體都是純POCO,並且不需要上下文跟蹤。
我讀過,任何上下文緩存/跟蹤被刪除,一旦使用塊處理ITAMEFContext。然而,它似乎有某種全局緩存在相同的應用程序域中的DBContext的任何實例下?我必須誠實地說,到目前爲止EF似乎比使用舊的存儲過程分層的應用程序更多的工作。
POCO。
public partial class Rollout
{
public Rollout()
{
this.AssetAssignees = new HashSet<AssetAssignee>();
}
public int ID { get; set; }
public string Name { get; set; }
public int RolloutLead_FK_User_ID { get; set; }
public string EmailContacts { get; set; }
public System.DateTime Schedule { get; set; }
public int FK_RolloutState_ID { get; set; }
public Nullable<int> NotificationDays { get; set; }
public string Notes { get; set; }
public virtual ICollection<AssetAssignee> AssetAssignees { get; set; }
public virtual User Lead { get; set; }
public virtual RolloutState RolloutState { get; set; }
}
編輯:
的映射。
internal partial class Rollout_Mapping : EntityTypeConfiguration<Rollout>
{
public Rollout_Mapping()
{
this.HasKey(t => t.ID);
this.ToTable("Rollout");
this.Property(t => t.ID).HasColumnName("ID");
this.Property(t => t.Name).HasColumnName("Name").IsRequired().HasMaxLength(50);
this.Property(t => t.RolloutLead_FK_User_ID).HasColumnName("RolloutLead_FK_User_ID");
this.Property(t => t.EmailContacts).HasColumnName("EmailContacts").HasMaxLength(500);
this.Property(t => t.Schedule).HasColumnName("Schedule");
this.Property(t => t.FK_RolloutState_ID).HasColumnName("FK_RolloutState_ID");
this.Property(t => t.NotificationDays).HasColumnName("NotificationDays");
this.Property(t => t.Notes).HasColumnName("Notes");
this.HasRequired(t => t.Lead).WithMany(t => t.Rollouts).HasForeignKey(d => d.RolloutLead_FK_User_ID);
this.HasRequired(t => t.RolloutState).WithMany(t => t.Rollouts).HasForeignKey(d => d.FK_RolloutState_ID);
}
}
在附加之前檢查「EntityState」的展開情況。如果已附加,請先將其分離(如果將導航屬性設置爲已跟蹤實體,則會自動添加新實體)。 – VahidN 2013-07-02 18:46:22