FrameworkTemplate/SolutionTemplate/Entities/Context/XrmExtensions.cs
using System; using System.Linq; using System.Collections.Generic; using System.Runtime.Serialization; using System.Linq.Expressions; using Microsoft.Xrm.Sdk; using Microsoft.Xrm.Sdk.Client; using Microsoft.Crm.Sdk.Messages; using Microsoft.Xrm.Sdk.Query; using Microsoft.Xrm.Sdk.Messages; namespace DG.XrmContext { public enum EmptyEnum { } public abstract partial class ExtendedEntity<State, Status> : Entity where State : struct, IComparable, IConvertible, IFormattable where Status : struct, IComparable, IConvertible, IFormattable { public ExtendedEntity(string entityName) : base(entityName) { } public ExtendedEntity(string entityName, Guid id) : base(entityName) { Id = id; } protected string GetDebuggerDisplay(string primaryNameAttribute) { string display = GetType().Name; var name = GetAttributeValue<string>(primaryNameAttribute); if (!string.IsNullOrEmpty(name)) display += string.Format(" ({0})", name); if (Id != Guid.Empty) display += string.Format(" [{0}]", Id); return display; } protected T? GetOptionSetValue<T>(string attributeName) where T : struct, IComparable, IConvertible, IFormattable { var optionSet = GetAttributeValue<OptionSetValue>(attributeName); if (optionSet != null) { return (T)Enum.ToObject(typeof(T), optionSet.Value); } else { return null; } } protected void SetOptionSetValue<T>(string attributeName, T value) { if (value != null) { SetAttributeValue(attributeName, new OptionSetValue((int)(object)value)); } else { SetAttributeValue(attributeName, null); } } protected IEnumerable<T> GetOptionSetCollectionValue<T>(string attributeName) where T : struct, IComparable, IConvertible, IFormattable { var optionSetCollection = GetAttributeValue<OptionSetValueCollection>(attributeName); if (optionSetCollection != null && optionSetCollection.Count != 0) { return optionSetCollection .Select(osv => (T)Enum.ToObject(typeof(T), osv.Value)) .ToArray(); } return null; } protected void SetOptionSetCollectionValue<T>(string attributeName, params T[] value) { if (value != null && value.Any()) { var arr = value .Select(v => new OptionSetValue((int)(object)v)) .ToArray(); SetAttributeValue(attributeName, new OptionSetValueCollection(arr)); } else { SetAttributeValue(attributeName, null); } } protected decimal? GetMoneyValue(string attributeName) { var money = GetAttributeValue<Money>(attributeName); if (money != null) { return money.Value; } else { return null; } } protected void SetMoneyValue(string attributeName, decimal? value) { if (value.HasValue) { SetAttributeValue(attributeName, new Money(value.Value)); } else { SetAttributeValue(attributeName, null); } } protected IEnumerable<T> GetEntityCollection<T>(string attributeName) where T : Entity { var collection = GetAttributeValue<EntityCollection>(attributeName); if (collection != null && collection.Entities != null) { return collection.Entities.Select(x => x as T); } else { return null; } } protected void SetEntityCollection<T>(string attributeName, IEnumerable<T> entities) where T : Entity { if (entities != null) { SetAttributeValue(attributeName, new EntityCollection(new List<Entity>(entities))); } else { SetAttributeValue(attributeName, null); } } protected void SetId(string primaryIdAttribute, Guid? guid) { base.Id = guid.GetValueOrDefault(); SetAttributeValue(primaryIdAttribute, guid); } protected KeyValuePair<string, object>[] DeltaAttributes; public void TagForDelta() { DeltaAttributes = new KeyValuePair<string, object>[Attributes.Count]; Attributes.CopyTo(DeltaAttributes, 0); } public void PerformDelta() { if (DeltaAttributes == null) return; var guid = Id; foreach (var prev in DeltaAttributes) { if (!Attributes.ContainsKey(prev.Key)) continue; if (Object.Equals(Attributes[prev.Key], prev.Value)) Attributes.Remove(prev.Key); } if (guid != Guid.Empty) Id = guid; } protected static T Retrieve_AltKey<T>(IOrganizationService service, KeyAttributeCollection keys, params Expression<Func<T, object>>[] attributes) where T : Entity { var req = new RetrieveRequest(); req.Target = new EntityReference(Activator.CreateInstance<T>().LogicalName, keys); req.ColumnSet = XrmExtensions.GetColumnSet(attributes); try { return (service.Execute(req) as RetrieveResponse)?.Entity?.ToEntity<T>(); } catch (System.ServiceModel.FaultException) { return null; } } public static string GetColumnName<T>(Expression<Func<T, object>> lambda) where T : Entity { MemberExpression body = lambda.Body as MemberExpression; if (body == null) { UnaryExpression ubody = (UnaryExpression)lambda.Body; body = ubody.Operand as MemberExpression; } if (body.Member.CustomAttributes != null) { var customAttributes = body.Member.GetCustomAttributesData(); var neededAttribute = customAttributes.FirstOrDefault(x => x.AttributeType == typeof(AttributeLogicalNameAttribute)); if (neededAttribute != null) { return neededAttribute.ConstructorArguments.FirstOrDefault().Value.ToString(); } } return body.Member.Name; } public static T Retrieve<T>(IOrganizationService service, Guid id, params Expression<Func<T, object>>[] attributes) where T : Entity { return service.Retrieve(id, attributes); } public SetStateResponse SetState(IOrganizationService service, State state) { return SetState(service, state, (Status)(object)-1); } public SetStateResponse SetState(IOrganizationService service, State state, Status status) { return service.Execute(MakeSetStateRequest(state, status)) as SetStateResponse; } public AssignResponse AssignTo(IOrganizationService service, EntityReference owner) { return service.Execute(MakeAssignRequest(owner)) as AssignResponse; } public SetStateRequest MakeSetStateRequest(State state, Status status) { var req = new SetStateRequest(); req.EntityMoniker = ToEntityReference(); req.State = new OptionSetValue((int)(object)state); req.Status = new OptionSetValue((int)(object)status); return req; } public AssignRequest MakeAssignRequest(EntityReference owner) { return new AssignRequest() { Assignee = owner, Target = ToEntityReference() }; } public CreateRequest MakeCreateRequest() { return new CreateRequest() { Target = this }; } public UpdateRequest MakeUpdateRequest() { return new UpdateRequest() { Target = this }; } public DeleteRequest MakeDeleteRequest() { return new DeleteRequest() { Target = ToEntityReference() }; } public UpsertRequest MakeUpsertRequest() { return new UpsertRequest() { Target = this }; } } public interface IEntity { object this[string attributeName] { get; set; } AttributeCollection Attributes { get; set; } EntityState? EntityState { get; set; } ExtensionDataObject ExtensionData { get; set; } FormattedValueCollection FormattedValues { get; } Guid Id { get; set; } string LogicalName { get; set; } RelatedEntityCollection RelatedEntities { get; } string RowVersion { get; set; } bool Contains(string attributeName); T GetAttributeValue<T>(string attributeLogicalName); T ToEntity<T>() where T : Entity; EntityReference ToEntityReference(); KeyAttributeCollection KeyAttributes { get; set; } } public abstract partial class ExtendedOrganizationServiceContext : OrganizationServiceContext { public ExtendedOrganizationServiceContext(IOrganizationService service) : base(service) { } public U Load<T, U>(T entity, Expression<Func<T, U>> loaderFunc) where T : Entity { LoadProperty(entity, XrmExtensions.GetAttributeLogicalName(loaderFunc)); return loaderFunc.Compile().Invoke(entity); } public IEnumerable<U> LoadEnumeration<T, U>(T entity, Expression<Func<T, IEnumerable<U>>> loaderFunc) where T : Entity { return Load(entity, loaderFunc) ?? new List<U>(); } } public static class XrmExtensions { public static T Retrieve<T>(this IOrganizationService service, Guid id, params Expression<Func<T, object>>[] attributes) where T : Entity { return service.Retrieve(Activator.CreateInstance<T>().LogicalName, id, GetColumnSet(attributes)).ToEntity<T>(); } public static UpsertResponse Upsert(this IOrganizationService service, Entity entity) { var req = new UpsertRequest() { Target = entity }; var resp = service.Execute(req) as UpsertResponse; entity.Id = resp.Target?.Id ?? entity.Id; return resp; } public static AssignResponse Assign(this IOrganizationService service, EntityReference target, EntityReference owner) { var req = new AssignRequest() { Target = target, Assignee = owner }; return service.Execute(req) as AssignResponse; } public static SetStateResponse SetState<T, U>(this IOrganizationService service, ExtendedEntity<T, U> entity, T state) where T : struct, IComparable, IConvertible, IFormattable where U : struct, IComparable, IConvertible, IFormattable { return entity.SetState(service, state); } public static SetStateResponse SetState<T, U>(this IOrganizationService service, ExtendedEntity<T, U> entity, T state, U status) where T : struct, IComparable, IConvertible, IFormattable where U : struct, IComparable, IConvertible, IFormattable { return entity.SetState(service, state, status); } public static List<ExecuteMultipleResponseItem> PerformAsBulk<T>(this IOrganizationService service, IEnumerable<T> requests, bool continueOnError = true, int chunkSize = 1000) where T : OrganizationRequest { var arr = requests.ToArray(); var splitReqs = from i in Enumerable.Range(0, arr.Length) group arr[i] by i / chunkSize; var resps = new List<ExecuteMultipleResponseItem>(); foreach (var rs in splitReqs) { var req = new ExecuteMultipleRequest(); req.Requests = new OrganizationRequestCollection(); req.Requests.AddRange(rs); req.Settings = new ExecuteMultipleSettings(); req.Settings.ContinueOnError = continueOnError; req.Settings.ReturnResponses = true; var resp = service.Execute(req) as ExecuteMultipleResponse; resps.AddRange(resp.Responses); } return resps; } public static ColumnSet GetColumnSet<T>(params Expression<Func<T, object>>[] attributes) { if (attributes == null) return new ColumnSet(); if (attributes.Length == 0) return new ColumnSet(true); return new ColumnSet(attributes.Select(a => GetAttributeLogicalName(a).ToLower()).ToArray()); } public static string GetAttributeLogicalName<T, U>(Expression<Func<T, U>> lambda) { MemberExpression body = lambda.Body as MemberExpression; if (body == null) { UnaryExpression ubody = (UnaryExpression)lambda.Body; body = ubody.Operand as MemberExpression; } var attributelogicalName = body.Member.GetCustomAttributes(false) .Where(x => x is AttributeLogicalNameAttribute) .FirstOrDefault() as AttributeLogicalNameAttribute; if (attributelogicalName == null) return body.Member.Name; return attributelogicalName.LogicalName; } public static bool ContainsAttributes<T>(this T entity, params Expression<Func<T, object>>[] attrGetters) where T : Entity { if (attrGetters == null) return true; return attrGetters.Select(a => GetAttributeLogicalName(a).ToLower()).All(a => entity.Contains(a)); } public static bool RemoveAttributes<T>(this T entity, params Expression<Func<T, object>>[] attrGetters) where T : Entity { if (attrGetters == null) return false; return attrGetters.Select(a => GetAttributeLogicalName(a).ToLower()).Any(a => entity.Attributes.Remove(a)); } } } |