如何将ObjectContext与Model Builder一起使用?

时间:2013-08-05 19:37:10

标签: entity-framework-5 dbcontext objectcontext

有没有办法可以在DbContext的ModelBuilder中使用ObjectContext?我们不想使用POCO,因为我们定制的属性代码不会在更新中修改整个对象,而只会更新已修改的属性。我们还有许多使用EntityObject的序列化和审计代码。

由于poco确实使用EntityObject创建了一个代理,我们希望我们的类是从EntityObject派生的。我们不想要代理。我们也大量使用CreateSourceQuery。唯一的问题是EDMX文件及其大连接字符串语法web.config。

有什么办法可以摆脱EDMX文件吗?它将非常有用,因为我们可以基于逆向工程数据库动态编译新类。

我还想将DbContext与EntityObject一起使用,而不是使用poco。

内部逻辑


  1. 访问保存更改中的修改后的属性,这些属性在ObjectStateEntry中可用并将其保存到具有旧值和新值的审核中
  2. 大多数情况下,我们只需检查导航属性上的任何条件,例如

  3.  User.EmailAddresses.CreateSourceQuery()
       .Any( x=> x.EmailAddress == givenAddress);
    

    1. 访问属性属性,例如XmlIgnore等,我们在很大程度上依赖于属性上定义的属性。

1 个答案:

答案 0 :(得分:4)

POCO的代理是动态创建的类,派生自(继承)POCO。只要POCO符合requirements,它就会添加先前在EntityObject中找到的功能,即延迟加载和更改跟踪。如问题所示,POCO或其代理不包含EntityObject,而是代理包含EntityObject的功能。您不能(AFAIK)将ModelBuilder与EntityObject衍生物一起使用,并且您无法从POCO或代理获取基础EntityObject,因为没有这样的。

我不知道您的现有序列化和审核代码使用ObjectContext的哪些功能,但您可以通过投射ObjectContextDbContext转到DbContextIObjectContextAdapter并访问IObjectContextAdapter.ObjectContext属性。

修改

1。访问保存更改中的已修改属性(可在ObjectStateEntry中使用,并将其保存到具有旧值和新值的审计

您可以使用DbContext.ChangeTracker通过POCO实现此目的。首先,您调用DbContext.ChangeTracker.DetectChanges来检测更改(如果您使用代理这不需要,但不会受到影响),然后使用DbCotnext.Entries.Where(e => e.State != EntityState.Unchanged && e.State != EntityState.Detached)获取DbEntityEntry已更改实体的列表以供审核。每个DbEntityEntry都有OriginalValuesCurrentValues,实际的实体位于属性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);