有没有办法可以在DbContext的ModelBuilder中使用ObjectContext?我们不想使用POCO,因为我们定制的属性代码不会在更新中修改整个对象,而只会更新已修改的属性。我们还有许多使用EntityObject的序列化和审计代码。
由于poco确实使用EntityObject创建了一个代理,我们希望我们的类是从EntityObject派生的。我们不想要代理。我们也大量使用CreateSourceQuery。唯一的问题是EDMX文件及其大连接字符串语法web.config。
有什么办法可以摆脱EDMX文件吗?它将非常有用,因为我们可以基于逆向工程数据库动态编译新类。
我还想将DbContext与EntityObject一起使用,而不是使用poco。
内部逻辑
User.EmailAddresses.CreateSourceQuery()
.Any( x=> x.EmailAddress == givenAddress);
答案 0 :(得分:4)
POCO的代理是动态创建的类,派生自(继承)POCO。只要POCO符合requirements,它就会添加先前在EntityObject
中找到的功能,即延迟加载和更改跟踪。如问题所示,POCO或其代理不包含EntityObject
,而是代理包含EntityObject
的功能。您不能(AFAIK)将ModelBuilder与EntityObject衍生物一起使用,并且您无法从POCO或代理获取基础EntityObject,因为没有这样的。
我不知道您的现有序列化和审核代码使用ObjectContext
的哪些功能,但您可以通过投射ObjectContext
从DbContext
转到DbContext
到IObjectContextAdapter
并访问IObjectContextAdapter.ObjectContext
属性。
修改强>
1。访问保存更改中的已修改属性(可在ObjectStateEntry中使用,并将其保存到具有旧值和新值的审计
您可以使用DbContext.ChangeTracker
通过POCO实现此目的。首先,您调用DbContext.ChangeTracker.DetectChanges
来检测更改(如果您使用代理这不需要,但不会受到影响),然后使用DbCotnext.Entries.Where(e => e.State != EntityState.Unchanged && e.State != EntityState.Detached)
获取DbEntityEntry
已更改实体的列表以供审核。每个DbEntityEntry
都有OriginalValues
和CurrentValues
,实际的实体位于属性Entity
。
您还可以访问ObjectStateEntry
,见下文。
2。大多数情况下,我们只需检查导航属性上的任何条件,例如:
User.EmailAddresses.CreateSourceQuery().Any( x=> x.EmailAddress == givenAddress);
如前所述,您可以通过使用IObjectContextAdapter将CreateSourceQuery()与DbContext一起使用。当你有ObjectContext时,你可以得到相关结束的源查询:
public static class DbContextUtils
{
public static ObjectQuery<TMember> CreateSourceQuery<TEntity, TMember>(this IObjectContextAdapter adapter, TEntity entity, Expression<Func<TEntity, ICollection<TMember>>> memberSelector) where TMember : class
{
var objectStateManager = adapter.ObjectContext.ObjectStateManager;
var objectStateEntry = objectStateManager.GetObjectStateEntry(entity);
var relationshipManager = objectStateManager.GetRelationshipManager(entity);
var entityType = (EntityType)objectStateEntry.EntitySet.ElementType;
var navigationProperty = entityType.NavigationProperties[(memberSelector.Body as MemberExpression).Member.Name];
var relatedEnd = relationshipManager.GetRelatedEnd(navigationProperty.RelationshipType.FullName, navigationProperty.ToEndMember.Name);
return ((EntityCollection<TMember>)relatedEnd).CreateSourceQuery();
}
}
此方法不使用动态代码,因为它使用表达式,所以它是强类型的。你这样使用它:
myDbContext.CreateSourceQuery(invoice, i => i.details);