Entity Framework - 11. ObjectQuery<T> (2)

[ 2009-04-01 11:36:47 | 作者: yuhen ]
字号: | |
2. Execute

不管是使用 LINQ foreach 方式,还是直接调用 Execute(),其执行流程都指向 GetResults()。
public class ObjectQuery<T> : ObjectQuery, ...
{
    IEnumerator<T> IEnumerable<T>.GetEnumerator()
    {
        IEnumerator<T> enumerator;
        ObjectResult<T> results = this.GetResults(null);
        try
        {
            enumerator = results.GetEnumerator();
        }
        catch
        {
            results.Dispose();
            throw;
        }
        return enumerator;
    }

    public ObjectResult<T> Execute(MergeOption mergeOption)
    {
        EntityUtil.CheckArgumentMergeOption(mergeOption);
        return this.GetResults(new MergeOption?(mergeOption));
    }
}

既然找到了线头,我们继续跟下去看看。
public class ObjectQuery<T> : ObjectQuery, ...
{
    private ObjectResult<T> GetResults(MergeOption? forMergeOption)
    {
        ObjectResult<T> result;
        base.QueryState.ObjectContext.EnsureConnection();

        try
        {
            result = base.QueryState.GetExecutionPlan(forMergeOption).
                Execute<T>(base.QueryState.ObjectContext, base.QueryState.Parameters);
        }
        catch
        {
            base.QueryState.ObjectContext.ReleaseConnection();
            throw;
        }
        
        return result;
    }

    public ObjectQuery(string commandText, ObjectContext context, MergeOption mergeOption) : 
        this(new EntitySqlQueryState(typeof(T), ...))
    {
        ...
    }
}

EntitySqlQueryState,很显然 ObjectQuery.PlanCachingEnabled 在 GetExecutionPlan() 中开始发挥作用。
internal sealed class EntitySqlQueryState : ObjectQueryState
{
    internal override ObjectQueryExecutionPlan GetExecutionPlan(MergeOption? forMergeOption)
    {
        ...

        if (base.PlanCachingEnabled)
        {
            ...

            if (queryCacheManager.TryCacheLookup(objectQueryCacheKey, out execPlan))
            {
                executionPlan = execPlan;
            }
        }

        if (executionPlan == null)
        {
            DbQueryCommandTree tree;
            tree = new DbQueryCommandTree(base.ObjectContext.MetadataWorkspace, DataSpace.CSpace) 
            {
                Query = this.Parse(tree)
            }
        };

        executionPlan = ObjectQueryExecutionPlan.Prepare(base.ObjectContext, tree, ...);

        if (objectQueryCacheKey != null)
        {
            ...

            if (queryCacheManager.TryLookupAndAdd(inQueryCacheEntry, out outQueryCacheEntry))
            {
                executionPlan = ((EntitySqlQueryCacheEntry) outQueryCacheEntry).ExecutionPlan;
            }
        }

        ...
        return executionPlan;
    }
}

ObjectQueryExecutionPlan 这个名字已经预示着我们即将看到一些更底层的东西。
internal sealed class ObjectQueryExecutionPlan
{
    internal static ObjectQueryExecutionPlan Prepare(ObjectContext context, DbQueryCommandTree tree, ...)
    {
        ...

        DbConnection connection = context.Connection;
        DbCommandDefinition commandDefinition = null;

        ...

        DbProviderServices providerServices = DbProviderServices.GetProviderServices(connection);
        ...
        commandDefinition = providerServices.CreateCommandDefinition(tree);

        ...

        EntityCommandDefinition definition2 = (EntityCommandDefinition) commandDefinition;
        QueryCacheManager queryCacheManager = context.Perspective.MetadataWorkspace.GetQueryCacheManager();
        ShaperFactory resultShaperFactory = ShaperFactory.Create(elementType, queryCacheManager, ...);

        ...

        return new ObjectQueryExecutionPlan(commandDefinition, resultShaperFactory, ...);
    } 
}

DbProvidersServices, DbConnection, DbCommandDefinition …… 路不多了。在得到 ObjectQueryExecutionPlan 对象后,ObjectQuery<T>.GetResults() 调用其 Execute()。
internal sealed class ObjectQueryExecutionPlan
{
    internal ObjectResult<TResultType> Execute<TResultType>(ObjectContext context, ...parameterValues)
    {
        DbDataReader reader = null;
        ObjectResult<TResultType> result;

        try
        {
            TypeUsage typeUsage;
            EntityCommandDefinition commandDefinition = (EntityCommandDefinition) this.CommandDefinition;
            EntityCommand entityCommand = new EntityCommand((EntityConnection) context.Connection, ...);

            ...

            reader = commandDefinition.ExecuteStoreCommands(entityCommand, CommandBehavior.Default);

            ...

            result = new ObjectResult<TResultType>(shaper, this._singleEntitySet, typeUsage);
        }
        catch (Exception)
        {
            ...
        }

        return result;
    }
}

EntityClient 要做的事情就已经很明了了,无需我们再说什么。

uploads/200904/01_113656_snap2.png
[最后修改由 yuhen, 于 2009-04-01 11:37:54]
评论Feed 评论Feed: http://www.rainsts.net/feed.asp?q=comment&id=799

这篇日志没有评论。

发表评论
表情图标
[smile] [confused] [cool] [cry]
[eek] [angry] [wink] [sweat]
[lol] [stun] [razz] [redface]
[rolleyes] [sad] [yes] [no]
[heart] [star] [music] [idea]
UBB代码
转换链接
表情图标
悄悄话
用户名:   密码:  
验证码 * 请输入验证码