2017-02-21 15 views
14

Kiedy jestem łączący adnotacje do konkretnego podmiotu, zamiast tworzenia relacji tak:Pierwsze wczesne związany związek

var associateRequest = new AssociateRequest 
{ 
    Target = new EntityReference(SalesOrder.EntityLogicalName, salesOrderGuid), 
    RelatedEntities = new EntityReferenceCollection 
    { 
     new EntityReference(Annotation.EntityLogicalName, noteGuid), 
    }, 
    Relationship = new Relationship("SalesOrder_Annotation") 
}; 

Czy można odwołać się do relacji w silnie wpisany sposób:

var associateRequest = new AssociateRequest 
{ 
    Target = new EntityReference(SalesOrder.EntityLogicalName, salesOrderGuid), 
    RelatedEntities = new EntityReferenceCollection 
    { 
     new EntityReference(Annotation.EntityLogicalName, noteGuid) 
    }, 
    Relationship = SalesOrder.Relationships.SalesOrder_Annotation // <----- ??? 
}; 

byłoby to podobne do bycia w stanie uzyskać logicalname na opracowanie czas:

SalesOrder.EntityLogicalName 

możemy odwoływać się do konkretnych 1: Zależność N w ten sam sposób:

SalesOrder.Relationships.SalesOrder_Annotation 
+0

Jaki jest typ zwracany przez 'SalesOrder.Relationships.SalesOrder_Annotation'? Jeśli to nie jest "Związek", to nie, nie możesz tego nazwać. Muszę zapytać, ponieważ 'SalesOrder.Relationships.SalesOrder_Annotation' nie jest dostępna przy użyciu standardowego narzędzia genów CrmSvcUtil.exe - więc jest to coś niestandardowego. – Nicknow

+0

są jakieś relacje, które są dostępne za pomocą crmsvcutil można wywoływać za pomocą entity.relationship name lub coś podobnego? –

+0

Nie. Musiałbyś utworzyć rozszerzenie, aby wygenerować ciągi "const" lub "readonly" z nazwami relacji. Lub napisać metodę odczytu nazwy relacji z atrybutu kodu wypisanego przez 'CrmSvcUtil.exe'. – Nicknow

Odpowiedz

4

Z tego, co pan powiedział, wygenerowanych klasy mają atrybut z nazwą relacji.
Wszystko czego potrzebujesz to szablon T4, który generuje klasy z silnie typami właściwości dla relacji

Powiedzmy masz następujący kod w swoim projekcie

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 { } 

} 

Ten szablon

<#@ 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 #>"; 
     } 
     <# } 

    #>} 
} 

wyświetli następujący plik .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"; 
     } 
    } 
} 

Wtedy można go używać jak

Relationship = new Relationship(Relationships.Class1.RelationShipA) 
+1

@Dvvoter Nie jestem pewien, czy ta odpowiedź zasługiwała na odrzucenie ... To może być bardziej skomplikowane niż inne, ale z drugiej strony nie ma kary za wyniki ... Jeśli OP chce użyć kodu to jest to prawdopodobnie najlepsza odpowiedź –

6

Wartość szukasz jest przechowywana w atrybucie kodu, RelationshipSchemaNameAttribute, jeśli wygenerować kod za pomocą standardowego CrmSvcUtil.exe aplikacji zawartych w SDK (\SDK\Bin\CrmSvcUtil.exe). Sprawdziłem poprawność tego kodu w aplikacji konsolowej, korzystając z pliku klasy wczesnych powiązań podanego w zestawie SDK (\SDK\SampleCode\CS\HelperCode\MyOrganizationCrmSdkTypes.cs).

wywołać metodę w następujący sposób (na swoim przykładzie):

var relationship = GetRelationship<SalesOrder>(nameof(SalesOrder.SalesOrder_Annotation))

Lub jeśli chcesz powrócić rzeczywistą wartość ciągu:

var relationshipName = GetRelationshipSchemaName<SalesOrder>(nameof(SalesOrder.SalesOrder_Annotation))

Dodaj ten kod do pomocnika klasa w aplikacji:

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); 
} 

To co się aktualizowany kod wyglądałby następująco:

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)) ///////////???? 
            }; 
5

Na drugim myśli, mój szablon T4 odpowiedź wydaje się przesadą
można użyć wyrażenia drzew i metodę rozszerzenia łatwo dostać co trzeba

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; } 
    } 
} 
4

Nie jestem pewien, czy dobrze odpowiedziałem na pytanie. Czy nie C# 6.0 funkcji nameof(...) zrobić coś?

tj.

new Relationship(nameof(RelationshipSalesOrder.Relationships.SalesOrder_Annotation)); 
+0

Problem (z tego co rozumiem) polega na tym, że "RelationshipSalesOrder.Relationships.SalesOrder_Annotation" nie istnieje. Jeśli istniał, tak, możesz to zrobić, –

+0

@GeorgeVovos jest poprawny. Nie ma "RelationshipSalesOrder.Relationships.SalesOrder_Annotation" i nawet gdyby istniał, niekoniecznie byłby zgodny z wartością ciągu potrzebną konstruktorowi 'Relationship'. – Nicknow

Powiązane problemy