有没有一种方法可以将实体标记为只读,并且不需要指定任何键?
有没有一种方法可以将实体标记为只读,并且不需要指定任何键?
有几种方法可以在Code First中强制只读。第一种是在查询时使用AsNoTracking()
。
var readOnlyPeople = (from p in context.People
where p.LastName == "Smith"
select p).AsNoTracking();
这告诉 Code First 不要跟踪这些实体的更改,因此当您调用 SaveChanges()
时,对这些对象所做的任何更改都不会被持久化。
第二件事是在调用 SaveChanges()
之前将状态设置为 Unchanged
。
context.Entry(person).State = EntityState.Unchanged;
context.SaveChanges();
这将告诉Code First忽略对该实体所做的任何更改。
至于没有键的情况,所有实体都必须有一个键。这可能不一定映射到数据库中的主键,但它“必须唯一标识实体集内的实体类型实例”。
在EF6中使用Code-First,我创建了一些反映视图的实体,这些实体显然不应该被修改或保存。为了防止实体被更改,我使用了protected set属性:
public class TransplantCenterView
{
public string TransplantsThisYear { get; protected set; }
}
Entity Framework仍然能够设置此属性,但其他开发人员无法在没有编译时错误的情况下意外更改它。这样做很好,但似乎更好的解决方案是完全消除跟踪。
感谢reggaeguitar的答案,看起来有一个解决方法(如果以下内容有帮助,请向他的答案投票),这使我可以将我的代码从以下方式更改:
public class MyContext : DbContext
{
public DbSet<TransplantCenterView> TransplantCenterViews { get; set; }
}
public class MyContext : DbContext
{
// appears the DbSet is still needed to make Set<Entity>() work
protected DbSet<TransplantCenterView> _transplantCenterViews { get; set; }
// this .AsNoTracking() disables tracking for our DbSet.
public DbQuery<TransplantCenterView> TransplantCenterViews
{
get { return Set<TransplantCenterView>().AsNoTracking(); }
}
}
我不知道这方面有什么利弊,但是我的现有代码继续运行没有遇到任何问题,所以看起来是一个胜利。
protected set
解决方案。 - Steven Ryssaert/// Using a dbquery since this is readonly.
/// </summary>
public DbQuery<State> States
{
get
{
// Don't track changes to query results
return Set<State>().AsNoTracking();
}
}
来源 http://www.adamtuliper.com/2012/12/read-only-entities-in-entity-framework.html
本文将介绍如何在Entity Framework中使用只读实体。只读实体是指只能被查询而不能被修改的实体对象。通过使用只读实体,可以提高应用程序的性能和安全性。protected DbSet<MyEntityName> _hiddenMyEntitiesName {get; set;}
然后问题就解决了。最好将 DbSet<> 添加到您上面的代码中,以便其他人不会遇到相同的困惑......或者是否有其他方法?但感谢您让我走上了正确的道路。 - Kevin Nelson你也可以通过类型将其设置为只读,作为更“全局”的规则来限制特定实体的修改。只需覆盖相应的SaveChanges*
方法,并在保存期间看到EF试图添加它时设置实体的状态。
public override Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default)
{
foreach (var entry in ChangeTracker.Entries())
{
if (entry.Entity.GetType() == typeof(<YOUR_TYPE_HERE>) && entry.State == EntityState.Added)
{
entry.State = EntityState.Detached;
}
}
return base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
}