关注本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复161或者20151015可方便获取本文,同时可以在第一时间得到我发布的最新的博文信息,follow me!
注释,这个实体的架构名称是Annotation,可能说成备注会稍微容易理解点吧。注释虽然不是活动实体的一种,但是也有类似活动实体一样的关于字段(ObjectId),可以关联到不同类型的实体记录,而我们自己创建的查找字段类型则只能关联到一种类型的实体记录。在创建实体的时候,实体是默认启用注释功能的,如下图所示,而且这个功能启用后是不能禁用的。
注释的显示和录入界面如下所示,可以看到和普通字段的录入及显示还是有点区别。注释可以包含附件,也可以不包含附件。
我们再来看看注释实体的元数据,系统中有两个实体的中文显示名称是注释,我们用实体的架构名称区分就容易找到了,常用的该实体属性有:主键字段 AnnotationId ,若注释包含附件,附件内容base64编码后存储在字段DocumentBody ,注释是否包括附件的字段 IsDocument ,注释附件的文件名字段FileName,注释附件的MIME类型字段 MimeType ,注释的文本内容字段 NoteText ,注释关联到的实体记录字段 ObjectId ,注释的标题字段 Subject 等等。
注释实体也是支持使用高级查询进行查找的:
class Program { static void Main(string[] args) { var service = GetOrganizationService(); var fetchXML = string.Format(@"<fetch mapping='logical' output-format='xml-platform' version='1.0' distinct='false'> <entity name='annotation'> <attribute name='subject' /> <attribute name='notetext' /> <attribute name='filename' /> <attribute name='mimetype' /> <attribute name='isdocument' /> <attribute name='ownerid' /> <attribute name='annotationid' /> <order descending='false' attribute='subject' /> <link-entity name='account' to='objectid' from='accountid' alias='ac'> <filter type='and'> <condition value='A. Datum%' attribute='name' operator='like' /> </filter> </link-entity> </entity> </fetch>"); EntityCollection ec = service.RetrieveMultiple(new FetchExpression(fetchXML)); Console.WriteLine("名称以A. Datum开头的客户的注释信息:"); var i = 1; foreach (var entity in service.RetrieveMultiple(new FetchExpression(fetchXML)).Entities) { Console.WriteLine("第" + i + "个注释:"); Console.WriteLine("注释主题:" + entity.GetAttributeValue<string>("subject")); Console.WriteLine("注释内容:" + entity.GetAttributeValue<string>("notetext")); Console.WriteLine("附件文件名称:" + entity.GetAttributeValue<string>("filename")); Console.WriteLine("附件文件MIME类型:" + entity.GetAttributeValue<string>("mimetype")); Console.WriteLine("注释是否包含附件:" + (entity.GetAttributeValue<bool>("isdocument")?"是":"否")); Console.WriteLine("注释ID:" + entity.GetAttributeValue<Guid>("annotationid")); Console.WriteLine("注释负责人:" + entity.GetAttributeValue<EntityReference>("ownerid").Name); Console.WriteLine("--------------------------------------------------"); i++; } Console.WriteLine("程序运行完成!"); Console.ReadKey(); }
执行结果如下:
我们用代码来新增一个不带附件和带附件的注释,代码如下:
static void Main(string[] args) { var service = GetOrganizationService(); var annotationEntity = new Entity("annotation"); //新增带不带附件的注释 annotationEntity["subject"] = "微软MVP罗勇用代码增加的不带附件的注释标题"; annotationEntity["notetext"] = "微软MVP罗勇用代码增加的不带附件的注释内容"; annotationEntity["isdocument"] = false; annotationEntity["objectid"] = new EntityReference("account", new Guid("858AB47F-494A-E511-80D2-000D3A802FAC")); service.Create(annotationEntity); //新增带附件的注释 annotationEntity = new Entity("annotation"); annotationEntity["subject"] = "微软MVP罗勇用代码增加的带附件的注释标题"; annotationEntity["notetext"] = "微软MVP罗勇用代码增加的带附件的注释内容"; annotationEntity["filename"] = "sugege.png"; using (FileStream fs = File.OpenRead(@"D:sugege.png")) { byte[] bytes = new byte[fs.Length]; fs.Read(bytes, 0, bytes.Length); annotationEntity["documentbody"] = Convert.ToBase64String(bytes); } annotationEntity["mimetype"] = "image/png"; annotationEntity["isdocument"] = true; annotationEntity["objectid"] = new EntityReference("account", new Guid("858AB47F-494A-E511-80D2-000D3A802FAC")); service.Create(annotationEntity); Console.WriteLine("程序运行完成!"); Console.ReadKey(); }
运行后结果如下,创建的附件是打开下载的。
这个实体还支持消息RollupRequest,英文版的解释是:Retrieves the annotations (notes) related to the specified record (account, contact, or opportunity). 中文大概意思获取某条记录(仅支持客户,联系人,商机实体)相关的注释。如果不做实验的话,你可能会不明白这个相关到底是啥意思吧?我们用代码来看看:
static void Main(string[] args) { var service = GetOrganizationService(); var annotationEntity = new Entity("annotation"); RollupRequest rollupreq = new RollupRequest(); QueryExpression qe = new QueryExpression(); qe.EntityName = "annotation"; qe.ColumnSet = new ColumnSet("subject","notetext","createdon","objectid"); qe.Distinct = false; qe.NoLock = true; qe.AddOrder("createdon", OrderType.Ascending); qe.Criteria = new FilterExpression { FilterOperator = LogicalOperator.And, Conditions = { new ConditionExpression("subject", ConditionOperator.NotNull) }, }; rollupreq.Query = qe; rollupreq.Target = new EntityReference("account", new Guid("858AB47F-494A-E511-80D2-000D3A802FAC")); rollupreq.RollupType = RollupType.Extended; RollupResponse rollupResponse = (RollupResponse)service.Execute(rollupreq); var i = 1; foreach (var entity in rollupResponse.EntityCollection.Entities) { Console.WriteLine("第" + (i+1) + "个注释:"); Console.WriteLine("注释主题:" + entity.GetAttributeValue<string>("subject")); Console.WriteLine("注释内容:" + entity.GetAttributeValue<string>("notetext")); Console.WriteLine("创建时间:" + entity.GetAttributeValue<DateTime>("createdon")); //objectid字段不能获取它的Name属性,囧 Console.WriteLine("是关于实体:" + entity.GetAttributeValue<EntityReference>("objectid").LogicalName + "的记录:" + entity.GetAttributeValue<EntityReference>("objectid").Id); i++; } Console.WriteLine("程序运行完成!"); Console.ReadKey(); }
结果是把这个客户,它的子客户,孙客户,孙客户的子客户,估计是以此类推的该客户及其所有下级客户所有的注释都拿出来了,结果如图:从我的测试结果来看,rollupreq.RollupType 设置为 RollupType.Extended 和 RollupType.Related 的效果是一样的,而设置为 RollupType.None 则是把所有的注释都取出来了,包括 不是客户实体的注释。
当然为了上面的代码更加好看到效果,我通过 客户的 上级单位 字段为目标客户建立了如下的层级关系:
表面上的说完了,我们稍微理解下在系统中是如何存储的,实体Annotation在数据库中对应了一个视图annotation,注意这个是视图,不是表,因为我对SQL还是比较熟悉的,所以大致看了下这个视图。这个视图中对应的基表是AnnotationBase,这个附件的名称,大小,内容等信息就存储在这个基表AnnotationBase中。这个和邮件的附件不同,了解邮件附件请参考我的前一篇博文:Dynamics CRM邮件附件,你真的了解吗?