[英]Getting an early-bound relationship
When I am linking annotations to a specific entity, rather than creating a relationship like so:当我将注释链接到特定实体时,而不是像这样创建关系:
var associateRequest = new AssociateRequest
{
Target = new EntityReference(SalesOrder.EntityLogicalName, salesOrderGuid),
RelatedEntities = new EntityReferenceCollection
{
new EntityReference(Annotation.EntityLogicalName, noteGuid),
},
Relationship = new Relationship("SalesOrder_Annotation")
};
Is it possible to reference the relationship in a strongly typed way:是否可以以强类型方式引用关系:
var associateRequest = new AssociateRequest
{
Target = new EntityReference(SalesOrder.EntityLogicalName, salesOrderGuid),
RelatedEntities = new EntityReferenceCollection
{
new EntityReference(Annotation.EntityLogicalName, noteGuid)
},
Relationship = SalesOrder.Relationships.SalesOrder_Annotation // <----- ???
};
This would be similar to being able to get the logicalname at develop time:这类似于能够在开发时获取逻辑名称:
SalesOrder.EntityLogicalName
Can we reference the specific 1:N relationship the same way:我们能否以同样的方式引用具体的 1:N 关系:
SalesOrder.Relationships.SalesOrder_Annotation
The value you are looking for is stored in a code attribute, RelationshipSchemaNameAttribute
, if you generate your code using the standard CrmSvcUtil.exe
application provided in the SDK ( \SDK\Bin\CrmSvcUtil.exe
).如果您使用 SDK (
\SDK\Bin\CrmSvcUtil.exe
) 中提供的标准CrmSvcUtil.exe
应用程序生成代码,则您要查找的值存储在代码属性RelationshipSchemaNameAttribute
中。 I've validated this code in a console application using the early bound entity class file provided in the SDK ( \SDK\SampleCode\CS\HelperCode\MyOrganizationCrmSdkTypes.cs
).我已经使用 SDK (
\SDK\SampleCode\CS\HelperCode\MyOrganizationCrmSdkTypes.cs
) 中提供的早期绑定实体类文件在控制台应用程序中验证了此代码。
Call the method as follows (per your example):按如下方式调用方法(根据您的示例):
var relationship = GetRelationship<SalesOrder>(nameof(SalesOrder.SalesOrder_Annotation))
Or if you want to return the actual string value:或者如果你想返回实际的字符串值:
var relationshipName = GetRelationshipSchemaName<SalesOrder>(nameof(SalesOrder.SalesOrder_Annotation))
Add this code to a helper class in your application:将此代码添加到应用程序中的帮助程序类:
public static string GetRelationshipSchemaName<T>(string relationshipPropertyName) where T:Entity
{
return typeof (T).GetProperties()
.FirstOrDefault(x => x.Name == relationshipPropertyName)
.GetCustomAttributes()
.OfType<RelationshipSchemaNameAttribute>()
.FirstOrDefault()
?.SchemaName;
}
public static Relationship GetRelationship<T>(string relationshipPropertyName) where T : Entity
{
return new Relationship(typeof(T).GetProperties()
.FirstOrDefault(x => x.Name == relationshipPropertyName)
.GetCustomAttributes()
.OfType<RelationshipSchemaNameAttribute>()
.FirstOrDefault()
?.SchemaName);
}
This is what your updated code would look like:这是您更新后的代码的样子:
var associateRequest = new AssociateRequest
{
Target =
new EntityReference(
SalesOrder.EntityLogicalName,
salesOrderGuid),
RelatedEntities =
new EntityReferenceCollection
{
new EntityReference(
Annotation
.EntityLogicalName,
noteGuid)
},
Relationship = GetRelationship<SalesOrder>(nameof(SalesOrder.SalesOrder_Annotation)) ///////////????
};
On second thought,my t4 template answer seems an overkill转念一想,我的 t4 模板答案似乎有点矫枉过正
You can use expression trees and an extension method to easily get what you need您可以使用表达式树和扩展方法轻松获得所需内容
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
namespace ConsoleApplication9
{
internal class Program
{
private static void Main(string[] args)
{
Relationship r = new Class1().GetRelationShip(s => s.RelationShipProperty);
Console.WriteLine(r.Name);
System.Console.ReadLine();
}
}
public static class MyExtention
{
public static Relationship GetRelationShip<T, TProperty>(this T t, Expression<Func<T, TProperty>> expression)
{
return new Relationship(((expression.Body as MemberExpression).Member as PropertyInfo)
.GetCustomAttributes(typeof(RelationshipAttribute))
.Select(a=>(RelationshipAttribute)a)
.First().Name
);
}
}
public class RelationshipAttribute : System.Attribute
{
public string Name { get; set; }
public RelationshipAttribute(string name)
{
Name = name;
}
}
public class Relationship
{
public string Name { get; set; }
public Relationship(string name)
{
Name = name;
}
}
public class Class1
{
[Relationship("RelationShipA")]
public List<int> RelationShipProperty { get; set; }
}
}
I'm not sure whether I got the question right.我不确定我是否答对了问题。 Wouldn't C# 6.0 feature
nameof(...)
do the thing? C# 6.0 功能
nameof(...)
不会做这件事吗?
ie. IE。
new Relationship(nameof(RelationshipSalesOrder.Relationships.SalesOrder_Annotation));
From what you said, your generated classes have an attribute with the name of your relationship.根据您所说,您生成的类有一个属性,其中包含您的关系名称。
All you need is a t4 template that generates a class with strongly typed properties for your Relationships您只需要一个 t4 模板,它可以为您的关系生成一个具有强类型属性的类
Let's say you have the following code in your project假设您的项目中有以下代码
namespace ConsoleApplication9
{
public class RelationshipAttribute : System.Attribute
{
public string Name { get; set; }
public RelationshipAttribute(string name) { Name = name; }
}
[Relationship("RelationShipA")]
public class Class1 { }
[Relationship("RelationShipB")]
public class Class2 { }
[Relationship("RelationShipC")]
public class Class3 { }
}
This template这个模板
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System" #>
<#@ assembly name="System.Core" #>
<#@ assembly name="$(TargetPath)" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System" #>
<#@ import namespace="System.Reflection" #>
<#@ output extension=".cs" #>
namespace YourNameSpace
{
public static class Relationships
{
<#
var types = typeof(ConsoleApplication9.RelationshipAttribute).Assembly
.GetTypes()
.Select(t => new { t.Name, Value = t.GetCustomAttribute(typeof(ConsoleApplication9.RelationshipAttribute)) })
.Where(t => t.Value != null)
.Select(t=> new { t.Name,Value= ((ConsoleApplication9.RelationshipAttribute)t.Value).Name })
.ToList();
foreach (var attr in types)
{ #>
public static class <#= attr.Name #>
{
public const string <#= attr.Value #> = "<#= attr.Value #>";
}
<# }
#>}
}
will produce the following.cs file会产生如下.cs文件
namespace YourNameSpace
{
public static class Relationships
{
public static class Class1
{
public const string RelationShipA = "RelationShipA";
}
public static class Class2
{
public const string RelationShipB = "RelationShipB";
}
public static class Class3
{
public const string RelationShipC = "RelationShipC";
}
}
}
Then you can use it like然后你可以像这样使用它
Relationship = new Relationship(Relationships.Class1.RelationShipA )
The Early Bound Generator in the XrmToolBox will generate these relationship names for you. XrmToolBox 中的 Early Bound Generator 将为您生成这些关系名称。
public static class Fields
{
public const string AccountId = "accountid";
public const string AccountRoleCode = "accountrolecode";
public const string Address1_AddressId = "address1_addressid";
// *** SNIP ***
public const string YomiLastName = "yomilastname";
public const string YomiMiddleName = "yomimiddlename";
public const string business_unit_contacts = "business_unit_contacts";
public const string contact_customer_accounts = "contact_customer_accounts";
public const string Referencingcontact_customer_contacts = "contact_customer_contacts";
public const string Referencingcontact_master_contact = "contact_master_contact";
public const string contact_owning_user = "contact_owning_user";
public const string lk_contact_createdonbehalfby = "lk_contact_createdonbehalfby";
public const string lk_contact_modifiedonbehalfby = "lk_contact_modifiedonbehalfby";
public const string lk_contactbase_createdby = "lk_contactbase_createdby";
public const string lk_contactbase_modifiedby = "lk_contactbase_modifiedby";
public const string system_user_contacts = "system_user_contacts";
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.