我正在通过SDK从Dynamics CRM 2011中提取项目实体列表,如下所示:
var projects = (from project in Context.ProjectSet
where project.ModifiedOn > DateTime.Now.AddHours(-1)
select new Project
{
Id = project.Id
}).ToList();
这样可以正常工作并返回正确数量的项目及其ID。
Project类是由CrmSvcUtil.exe自动生成的,并存储在如下的部分类中:
Entities.cs
(真正的文件要大得多,我把它剪下来了)
[assembly: Microsoft.Xrm.Sdk.Client.ProxyTypesAssembly()]
namespace Framework.CRM
{
public partial class Project : Microsoft.Xrm.Sdk.Entity, System.ComponentModel.INotifyPropertyChanging, System.ComponentModel.INotifyPropertyChanged
{
// There are lots of properties and events etc here
// Here's one example of a property for brevity
[Microsoft.Xrm.Sdk.AttributeLogicalName("createdby")]
public Microsoft.Xrm.Sdk.EntityReference CreatedBy
{
get
{
return GetAttributeValue<Microsoft.Xrm.Sdk.EntityReference>("createdby");
}
}
}
}
有些自动生成的属性没有setter,因此在运行查询时无法存储它们的值。因为它是自动生成的代码,所以我没有修改它,而是使用一些额外的属性扩展类,如下所示:
CustomProperties.cs
namespace Framework.CRM
{
using System;
public partial class Project
{
public Guid CustomerGuid { get; set; }
public DateTime? LastUpdated { get; set; }
// It's only the nullable DateTime because CRM implements
// that for some reason even though it's never null
}
}
我现在可以使用相同的查询,但这次我可以存储一些我以前无法解决的属性:
var projects = (from project in Context.ProjectSet
where project.ModifiedOn > DateTime.Now.AddHours(-1)
select new Project
{
Id = project.Id,
LastUpdated = project.ModifiedOn,
CustomerGuid = project.CompanylinkId != null ? project.CompanylinkId.Id : Guid.Empty
}).ToList();
这仍然会获取正确数量的项目并填充Id
属性,但我的所有自定义属性都为空,我无法理解为什么。我可以向您保证,ModifiedOn
和CompanylinkId
在CRM中不为空。
例如:
foreach (var project in projects)
{
Console.WriteLine(project.Id.ToString());
Console.WriteLine(project.LastUpdated?.ToString("dd/MM/yyyy"));
}
输出:
{40e74702-d17b-4598-b4a0-150b353459a4}
{134aa5bd-aef3-4489-93c2-a3c0bdebd20a}
预期:
{40e74702-d17b-4598-b4a0-150b353459a4}
18/11/2016
{134aa5bd-aef3-4489-93c2-a3c0bdebd20a}
2016/11/17
更令人沮丧的是,这次上次我做了这个工作,并且我让旧项目与新项目并排坐着,看不出我必须做些什么才能修复它。 我是否以某种方式错误地使用了部分类和LINQ查询?
修改
有趣的是,如果我更改查询以选择现有项目而不是创建新项目,那么它可以正常工作:
var projects = (from project in Context.ProjectSet
where project.ModifiedOn > DateTime.Now.AddHours(-1)
select project).ToList();
我真的不想这样做,因为我只想要数百个中的六个字段,这相当于select * from
。
答案 0 :(得分:1)
这是我对标准CrmSvcUtil生成的类的挫折之一。他们不允许设置只读字段,除非您检索整个课程,这是一种不好的做法。
为了帮助解决这个问题,我在XrmToolBox的EarlyBoundGenerator中写了一个更改为&#34; Generate AnonymousType Constructors&#34;
/// <summary>
/// Constructor for populating via LINQ queries given a LINQ anonymous type
/// <param name="anonymousType">LINQ anonymous type.</param>
/// </summary>
[System.Diagnostics.DebuggerNonUserCode()]
public Project(object anonymousType) :
this()
{
foreach (var p in anonymousType.GetType().GetProperties())
{
var value = p.GetValue(anonymousType, null);
var name = p.Name.ToLower();
if (name.EndsWith("enum") && value.GetType().BaseType == typeof(System.Enum))
{
value = new Microsoft.Xrm.Sdk.OptionSetValue((int) value);
name = name.Remove(name.Length - "enum".Length);
}
switch (name)
{
case "id":
base.Id = (System.Guid)value;
Attributes["projectid"] = base.Id;
break;
case "productid":
var id = (System.Nullable<System.Guid>) value;
if(id == null){ continue; }
base.Id = id.Value;
Attributes[name] = base.Id;
break;
case "formattedvalues":
// Add Support for FormattedValues
FormattedValues.AddRange((Microsoft.Xrm.Sdk.FormattedValueCollection)value);
break;
default:
Attributes[name] = value;
break;
}
}
}
然后,您可以将查询更改为:
var projects = (from project in Context.ProjectSet
where project.ModifiedOn > DateTime.Now.AddHours(-1)
select new Project(new {
{
project.Id,
project.ModifiedOn,
project.CompanylinkId
}).ToList();
这有两件好事:
如果您愿意,可以复制并粘贴构造函数,切换到使用EarlyBoundGenerator,或者更直接地回答您的问题,了解为什么您的值不会被填充,很可能是因为您实际上并未将值放入实体的AttributeCollection属性中。当从实体转换为您定义的类型时,CRM会做一些有趣的优化。