2

有没有办法可以将 ObjectContext 与 DbContext 的 ModelBuilder 一起使用?我们不想使用 POCO,因为我们有自定义的属性代码,它不会在更新中修改整个对象,而只会更新修改后的属性。此外,我们还有很多使用 EntityObject 的序列化和审计代码。

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

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

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

内部逻辑


  1. 访问 ObjectStateEntry 中可用的 Save Changes 中的已修改属性,并使用旧值和新值将它们保存到 Audit 中
  2. 大多数时候,我们只需要检查 Navigation Property 上的 Any 条件,例如

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

  1. 访问Property Attributes,例如XmlIgnore 等,我们严重依赖在属性上定义的属性。
4

1 回答 1

4

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

我不知道ObjectContext您现有的序列化和审计代码使用了哪些功能,但是您可以通过将 a 转换为 a并访问属性来ObjectContext从 a获取。DbContextDbContextIObjectContextAdapterIObjectContextAdapter.ObjectContext

编辑:

1. 访问 ObjectStateEntry 中可用的 Save Changes 中的已修改属性并将它们保存到 Audit 中,并使用旧值和新值

您可以通过使用 POCO 来实现这一点DbContext.ChangeTracker。首先,您调用DbContext.ChangeTracker.DetectChanges以检测更改(如果您使用代理,这不是必需的,但不会受到伤害),然后您使用DbCotnext.Entries.Where(e => e.State != EntityState.Unchanged && e.State != EntityState.Detached)获取DbEntityEntry更改实体的列表以进行审计。每个DbEntityEntry都有OriginalValues并且CurrentValues实际的 Entity 在 property 中Entity

您还可以访问ObjectStateEntry,见下文。

2. 大多数时候,我们只需要检查 Navigation Property 上的 Any 条件,例如:

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);
于 2013-08-16T19:55:43.413 回答