需要为错过工作流程活动的联系人创建报告

时间:2012-01-13 20:24:57

标签: sql dynamics-crm dynamics-crm-2011

我们遇到的问题是我们的工作流程尚未创建活动。

我现在需要报告哪些帐户没有调用其工作流程。

我尝试过高级查找,然后转移到sql。

我的问题是,有人可以提供一个简单的启动查询来拉出哪个“实体”没有与之关联的特定活动吗?

如果问题不够明确或需要更多信息,请告诉我。

1 个答案:

答案 0 :(得分:1)

下面是一个使用SQL的解决方案,我逐步完成了我的思考过程,下面是一个使用C#API开始的解决方案(编辑:刚刚意识到这是一个报告,因此可以忽略该部分)。我在大多数地方评论过,所以我希望我的方法相当直接。

SQL

1

--get all the entities that aren't activities and aren't intersect entities (N:N tables)
--Put in your own where conditions to further filter this list,
--which is still probably far too expansive
SELECT
    A.name EntityName
FROM MetadataSchema.Entity A
WHERE 
    A.IsActivity = 0
        AND A.IsIntersect = 0

2

--CROSS JOIN the non-activity entities with the activity entities
--to get a list of all possible entity/activity pairings
SELECT DISTINCT
    A.name EntityName
    , B.Name ActivityName
FROM MetadataSchema.Entity A
    CROSS JOIN MetadataSchema.Entity B
WHERE 
    A.IsActivity = 0
        AND A.IsIntersect = 0
        AND B.IsActivity = 1

3

--LEFT JOIN the partial cartesian join above against the Activity table,
--making a note of which entities actually have activity records.
--This will provide a complete list of which entity/activity pairings
--exist and don't exist
SELECT
    A.name EntityName
    , B.Name ActivityName
    --if there is a matching activity, the unique key,
    --ActivityTypeCode (int), will be positive.
    --So, if there is a positive sum for an entity/activity
    --pairing, you know there is a valid pair; otherwise
    --no pair
    , CAST(CASE WHEN sum(coalesce(C.ActivityTypeCode, 0)) > 0
        THEN 1
    ELSE 0
    END AS BIT) EntityOwnsActivity  
FROM MetadataSchema.Entity A
    CROSS JOIN MetadataSchema.Entity B
    LEFT JOIN dbo.ActivityPointer C ON
        --ObjectTypeCode is a unique identifier for Entities;
        --RegardingObjectTypeCode is the code for the entity type
        --associated with a particular activity
        A.ObjectTypeCode = C.RegardingObjectTypeCode
        --ActivityTypeCode is the code for the particular activity
            AND B.ObjectTypeCode = C.ActivityTypeCode
WHERE 
    A.IsActivity = 0
        AND A.IsIntersect = 0
        AND B.IsActivity = 1
GROUP BY 
    A.name
    , B.Name

4

--Putting it all together, using the above master table,
--filter out the entities/activities you're interested in
--(in this case, all entities that aren't associated with
--any emails)
SELECT 
    EntityName
FROM
(
    SELECT
        A.name EntityName
        , B.Name ActivityName
        , CAST(CASE WHEN sum(coalesce(C.ActivityTypeCode, 0)) > 0
            THEN 1
        ELSE 0
        END AS BIT) EntityOwnsActivity  
    FROM MetadataSchema.Entity A
        CROSS JOIN MetadataSchema.Entity B
        LEFT JOIN dbo.ActivityPointer C ON
            A.ObjectTypeCode = C.RegardingObjectTypeCode
                AND B.ObjectTypeCode = C.ActivityTypeCode
    WHERE 
        A.IsActivity = 0
            AND A.IsIntersect = 0
            AND B.IsActivity = 1
    GROUP BY 
        A.name
        , B.Name
) EntityActivities
WHERE ActivityName = 'Email'
    AND EntityOwnsActivity = 0
ORDER BY
    EntityName

C#.NET API

using (OrganizationServiceProxy _serviceProxy = 
        new OrganizationServiceProxy(
        new Uri(".../XRMServices/2011/Organization.svc"), null, null, null))
{
    _serviceProxy.EnableProxyTypes();

    RetrieveAllEntitiesRequest request = new RetrieveAllEntitiesRequest()
    {
        EntityFilters = EntityFilters.Entity,
        RetrieveAsIfPublished = true
    };

    // Retrieve the MetaData.
    EntityMetadata[] entities = 
            ((RetrieveAllEntitiesResponse)_serviceProxy.Execute(request)).EntityMetadata;

    var ents = from e1 in entities.Where(x => x.IsActivity != true)
                                  .Where(x => x.IsIntersect != true)
               from e2 in entities.Where(x => x.IsActivity == true)
               select new
               {
                   entityName = e1.SchemaName
                   ,
                   activityName = e2.SchemaName
               };
    //at this point, because of the limited nature of the Linq provider for left joins
    //and sums, probably the best approach is to do a fetch query on each entity/activity
    //combo, do some sort of sum and find out which combos have matches
    // in the activity pointer table

    //API = very inefficient; maybe improved in next CRM release? Let's hope so!

}