Dynamics 365 v8.2.2.
Why attributesMetadata is null? How can I get the entity attributes metadata list?
{
var req = new RetrieveEntityRequest {
LogicalName = "opportunity",
RetrieveAsIfPublished = true,
};
var resp = srv.Execute(req) as RetrieveEntityResponse;
var entityMetadata = resp.EntityMetadata;
var attributesMetadata = entityMetadata.Attributes; // null
}
You need to set EntityFilters in request like:
EntityFilters = EntityFilters.All
Or
EntityFilters = EntityFilters.Attributes
The complete snippet as follows:
RetrieveEntityRequest retrieveEntityRequest = new RetrieveEntityRequest
{
EntityFilters = EntityFilters.Attributes,
LogicalName = "opportunity"
};
RetrieveEntityResponse retrieveOpptyEntityResponse(RetrieveEntityResponse)service.Execute(retrieveEntityRequest);
EntityMetadata opptyEntity = retrieveOpptyEntityResponse.EntityMetadata;
By default, EntityFilters.Default only entity information will be retrieved, that’s why you have empty attribute list.
Read more
Related
I have two tables with similar data for body insurance and third party car insurance ... I have used enum in the model to separate the insurances and I want to do the creation operation for it .... There are two modes for each insurance. One case when that car does not have insurance yet and the second case when we want to extend it.
I wrote this code to create the form, but it encounters the following error
I also get an error on the name of the Create function.error = not all code paths return a value.
Please advise
public async Task<IActionResult> Create(int id, int type)
{
InsuranceViewModel model;
ViewBag.Type = type;
var companies = await _context.InsuranceCompany
.Where(e => e.IsActice)
.ToListAsync();
ViewData["CompanyList"] = new SelectList(companies, "Id", "CompanyName");
if ((InsuranceType)type == InsuranceType.Body)
{
var bodyInsurance = await _context.BodyInsurance
.Include(e => e.InsuranceCompany)
.FirstOrDefaultAsync(e => e.Id == id);
if (bodyInsurance == null)
{
model = new InsuranceViewModel
{
CompanyId = bodyInsurance.InsuranceCompanyId,
CompanyName = bodyInsurance.InsuranceCompany.CompanyName,
InsuranceType = InsuranceType.Body,
IssueDate = new DateTime(bodyInsurance.IssueDate).Ticks,
ExpireDate = new DateTime(bodyInsurance.ExpireDate).Ticks,
VehicleInformationId = id
};
}
else
{
var lastBody = await _context.BodyInsurance.Include(e => e.InsuranceCompany)
.Where(e => e.VehicleInformationId == id)
.OrderBy(e => e.ExpireDate)
.LastAsync();
model = new InsuranceViewModel
{
ExpireDate = new DateTime(lastBody.ExpireDate).AddYears(1).AddDays(1).Ticks,
CompanyId = lastBody.InsuranceCompanyId,
CompanyName = lastBody.InsuranceCompany.CompanyName,
InsuranceType = InsuranceType.Body,
IssueDate = new DateTime(lastBody.ExpireDate).AddDays(1).Ticks,
VehicleInformationId = id
};
}
}
else
{
if ((InsuranceType)type == InsuranceType.Thirdpart)
{
var thirdParty = await _context.ThirdPartyInsurance
.Include(e => e.InsuranceCompany)
.FirstOrDefaultAsync(e => e.Id == id);
if (thirdParty == null)
{
model = new InsuranceViewModel
{
CompanyId = thirdParty.InsuranceCompanyId,
CompanyName = thirdParty.InsuranceCompany.CompanyName,
InsuranceType = InsuranceType.Body,
IssueDate = new DateTime(thirdParty.IssueDate).Ticks,
ExpireDate = new DateTime(thirdParty.ExpireDate).Ticks,
VehicleInformationId = id
};
}
else
{
var lastThirdParty = await _context.ThirdPartyInsurance.Include(e => e.InsuranceCompany)
.Where(e => e.VehicleInformationId == id)
.OrderBy(e => e.ExpireDate)
.LastAsync();
model = new InsuranceViewModel
{
ExpireDate = new DateTime(lastThirdParty.ExpireDate).AddYears(1).AddDays(1).Ticks,
CompanyId = lastThirdParty.InsuranceCompanyId,
CompanyName = lastThirdParty.InsuranceCompany.CompanyName,
InsuranceType = InsuranceType.Body,
IssueDate = new DateTime(lastThirdParty.ExpireDate).AddDays(1).Ticks,
VehicleInformationId = id
};
}
}
return View(model);
}
I am trying to add a range of values from four distinct list of objects to a list. This is the code I have to add all the items from one list of objects...
var formList = new List<FormList>();
formList = forms.LimitedWillForms.Select(a => new FormList()
{
DateCreated = a.CreationDate,
FormId = a.Id,
FormType = a.FormType,
Submitted = a.SubmissionDate != null
}).ToList();
I am trying to not just add from the forms.LimitedWillForms list, but also from the forms.FullWillForms, and the forms.FullWillForms2, and the forms.FullWillForms3 too, adding the same parameters. This seems to work to add selected parameters from the form to the list.
I am not sure of the most efficient way to use linq to add selected parameters from all four lists to the formList. Can anyone help?
Since the lists contain objects of different types your best option would be to add an common interface to all the types for the common properties.
public interface IRecord
{
DateTime DateCreated {get;set;}
int FormId {get;set;}
....
}
You can then do:
var formList = forms.LimitedWillForms
.Cast<IRecord>
.Concat(forms.FullWillForms)
.Concat(forms.FullWillForms2)
.Concat(forms.FullWillForms3)
.Select(x => new FormList()
{
DateCreated = x.CreationDate,
FormId = x.Id,
FormType = x.FormType,
Submitted = x.SubmissionDate != null
}).ToList();
If you can live with just getting back a list if IRecord instead of FormList you can actually skip the last select.
If that is not possible you would need to select the properties from each collection.
var formList = forms.LimitedWillForms.Select(x => new FormList()
{
DateCreated = x.CreationDate,
FormId = x.Id,
FormType = x.FormType,
Submitted = x.SubmissionDate != null
}).Concat(
forms.FullWillForms.Select(x => new FormList()
{
DateCreated = x.CreationDate,
FormId = x.Id,
FormType = x.FormType,
Submitted = x.SubmissionDate != null
}
).Concat(...).ToList();
Try this:
var formList = forms.LimitedWillForms.Select(a => new FormList
{
DateCreated = a.CreationDate,
FormId = a.Id,
FormType = a.FormType,
Submitted = a.SubmissionDate != null
})
.Union(forms.FullWillForms.Select(a => new FormList
{
DateCreated = a.CreationDate,
FormId = a.Id,
FormType = a.FormType,
Submitted = a.SubmissionDate != null
}))
.Union(forms.FullWillForms2.Select(a => new FormList
{
DateCreated = a.CreationDate,
FormId = a.Id,
FormType = a.FormType,
Submitted = a.SubmissionDate != null
}))
.Union(forms.FullWillForms3.Select(a => new FormList
{
DateCreated = a.CreationDate,
FormId = a.Id,
FormType = a.FormType,
Submitted = a.SubmissionDate != null
})).ToList();
I have something like this which is getting string categories (from dropdown).
I am taking all list in catList and comparing that item in string[]categories and if it is null add this to newCategories for add to database. And lastly i want to return List<Category> with categories values.
public List<Category> ExistingCategories(string[] categories)
{
var catList = GetAllCategories().ToList();
List<Category> newCategories = new List<Category>();
var existedCategory = catList.ToLookup(x=>x.Name , v=>v.Name);
foreach (var item in categories)
{
var lookUpExistedCategory = existedCategory[item];
if (lookUpExistedCategory != )
{
newCategories.Add(new Category { Name = item });
}
}
CreateCategories(newList);
return GetAllCategories().ToList();
}
How should I do that?
You can use .Contains(TKey value)
So you can replace your foreach loop by
var newCategories = categories
.Where(m => !existedCategory.Contains(m))
.Select(m => new Category{Name = m}).toList()
By the way, I don't see the need of a LookUp<TKey, TValue>, you could use a HashSet<T>
var existedCategory = new HashSet(GetAllCategories().Select(x => x.Name).ToList());
So your method would be
public List<Category> ExistingCategories(string[] categories)
{
var existingCategories = new HashSet(GetAllCategories().Select(x => x.Name).ToList());
var newCategories = categories
.Where(m => !existingCategories .Contains(m))
.Select(m => new Category{Name = m}).toList());
//assuming this method will add and save to your db
CreateCategories(newCategories);
return GetAllCategories().ToList();
}
I'm trying to implement a DevExpress MVC TreeList that shows a list of clients as the first level of the hierarchy. But when you open one client, the second level must show a list of related orders with their OrderTotal for each order.
I'm trying to base myself on the demo at http://demos.devexpress.com/MVCxTreeListDemos/DataBinding/DataBinding which is similar to what I'm looking for. I'm using the Northwind database as an example.
The model that the TreeList must be based on has to be specific in that it has to have the following structure (maybe I'm wrong on this):
CustomerId,
Order.CustomerId,
CustomerName,
OrderTotal,
OrderDate,
ShipCity
The second one has to be the "ParentId" in order to satisfy the hierarchy structure.
Here is what I have in my controller:
[ValidateInput(false)]
public ActionResult OrderTreeListPartial()
{
var model = db.Orders.GroupBy(o => o.Customer)
.Select(group => new
{
CustomerId = group.Key.CustomerID,
ParentId = group.Select(g=>g.CustomerID),
CustomerName = group.Key.CompanyName,
OrderTotal = group.Sum(g => g.OrderTotal),
OrderDate = group.Select(g => g.OrderDate),
City = group.Select(g => g.ShipCity)
});
return PartialView("_OrderTreeListPartial", model);
}
And I have the following in my _OrderTreeListPartial:
#{
var treeList = Html.DevExpress().TreeList(settings =>
{
settings.Name = "OrderTreeList";
settings.CallbackRouteValues = new { Controller = "TreeList", Action = "OrderTreeListPartial" };
settings.SettingsEditing.AddNewNodeRouteValues = new { Controller = "TreeList", Action = "OrderTreeListPartialAddNew" };
settings.SettingsEditing.UpdateNodeRouteValues = new { Controller = "TreeList", Action = "OrderTreeListPartialUpdate" };
settings.SettingsEditing.DeleteNodeRouteValues = new { Controller = "TreeList", Action = "OrderTreeListPartialDelete" };
settings.SettingsEditing.NodeDragDropRouteValues = new { Controller = "TreeList", Action = "OrderTreeListPartialMove" };
settings.CommandColumn.Visible = true;
settings.CommandColumn.NewButton.Visible = true;
settings.CommandColumn.DeleteButton.Visible = true;
settings.CommandColumn.EditButton.Visible = true;
settings.AutoGenerateColumns = false;
settings.KeyFieldName = "CustomerId";
settings.ParentFieldName = "ParentId";
settings.RootValue = 0;
settings.Columns.Add(
column =>
{
column.FieldName = "CustomerName";
}
);
settings.Columns.Add(
column =>
{
column.FieldName = "OrderDate";
}
);
settings.Columns.Add(
column =>
{
column.FieldName = "OrderTotal";
column.PropertiesEdit.DisplayFormatString = "{0:C}";
}
);
settings.Columns.Add(
column =>
{
column.FieldName = "City";
}
);
settings.SettingsPager.Visible = true;
settings.SettingsSelection.Enabled = true;
});
if (ViewData["EditError"] != null)
{
treeList.SetEditErrorText((string)ViewData["EditError"]);
}
}
#treeList.Bind(Model).GetHtml()
I think the problem is in my LINQ expression in my controller. The truth is I'm not an expert in LINQ and I'm evaluating the DevExpress extensions for a future project. Any help would be appreciated, wether in my LINQ or in how I prepared the TreeList.
You didn't really specify your problem but I think you shouldn't do the grouping in advance as this results in list of groups.
Just create a DataTable with the columns "CustomerId" and "ParentId".
The TreeList will then do the grouping
I have that lambda:
var Ids = profileExample.CostCenters
.Where(CostCentre => CostCentre != null)
.Select(CostCentre => CostCentre.Id);
Then i convert to that expression tree
static IEnumerable<Int64> AboveLambdaConvertedToExpressionTree(Profile profileExample)
{
//Begin var Ids = profileExample.CostCenters.Where(CostCentre => CostCentre != null).Select(CostCentre => CostCentre.Id);
var property = profileExample.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(x => x.Name != "Id").First();
var collection = ((IEnumerable)property.GetValue(profileExample, null)).AsQueryable();
var collectionType = property.PropertyType.GetGenericArguments()[0];
var collectionTypeName = collectionType.Name;
var keyType = typeof(Int64);
var keyName = "Id";
//BeginWhere
var parameter = Expression.Parameter(collectionType, collectionTypeName);
var profileExampleWhere = Expression.Lambda(
Expression.NotEqual(parameter, Expression.Constant(null)),
parameter);
var profileExampleWhereCall = Expression.Call(typeof(Enumerable),
"Where",
new Type[] { collectionType },
collection.Expression,
profileExampleWhere);
//EndWhere
//BeginSelect
var profileExampleSelect = Expression.Lambda(Expression.PropertyOrField(parameter, keyName),
parameter);
var profileExampleSelectCall = Expression.Call(typeof(Enumerable),
"Select",
new Type[] { collectionType, keyType },
profileExampleWhereCall,
profileExampleSelect);
var Ids = Expression.Lambda(profileExampleSelectCall).Compile().DynamicInvoke();
//EndSelect
//End var Ids = profileExample.CostCenters.Where(CostCentre => CostCentre != null).Select(CostCentre => CostCentre.Id);
return ((IEnumerable)Ids).Cast<Int64>();
}
Now i want to do the same with bellow lambda
var result = Set.AsQueryable()
.Where(Profile => Profile.CostCenters.Select(CostCentre => CostCentre.Id)
.Any(Id => Ids.Contains(Id))).ToList();
But i stuck in .Any(Id => Ids.Contains(Id))....
var id = Expression.Parameter(typeof(long), "Id");
var costCentre = Expression.Parameter(typeof(CostCentre), "CostCentre");
var profile = Expression.Parameter(typeof(Profile), "Profile");
var selectLambda = Expression.Lambda(Expression.PropertyOrField(costCentre, "Id"), costCentre);
var selectCall = Expression.Call(typeof(Enumerable),
"Select",
new Type[] { typeof(CostCentre), typeof(long) },
Expression.PropertyOrField(profile, "CostCenters"),
selectLambda);
How can i call Any from selectCall and call Ids.Contains...
Full code to run as console application bellow:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
namespace ExpressionTrees
{
class Program
{
static void Main(string[] args)
{
var Ids = profileExample.CostCenters.Where(CostCentre => CostCentre != null).Select(CostCentre => CostCentre.Id);
Ids = AboveLambdaConvertedToExpressionTree(profileExample);
var result = Set.AsQueryable().Where(Profile => Profile.CostCenters.Select(CostCentre => CostCentre.Id).Any(Id => Ids.Contains(Id))).ToList();
//Expression<Func<Profile, bool>> lambda = (Profile) => Profile.CostCenters.Select(CostCentre => CostCentre.Id).Any(Id => Ids.Contains(Id));
var id = Expression.Parameter(typeof(long), "Id");
var costCentre = Expression.Parameter(typeof(CostCentre), "CostCentre");
var profile = Expression.Parameter(typeof(Profile), "Profile");
var selectLambda = Expression.Lambda(Expression.PropertyOrField(costCentre, "Id"), costCentre);
var selectCall = Expression.Call(typeof(Enumerable),
"Select",
new Type[] { typeof(CostCentre), typeof(long) },
Expression.PropertyOrField(profile, "CostCenters"),
selectLambda);
}
static IEnumerable<Int64> AboveLambdaConvertedToExpressionTree(Profile profileExample)
{
// I show that as example of what i need to do
var keyType = typeof(Int64);
var keyName = "Id";
//Begin var Ids = profileExample.CostCenters.Where(CostCentre => CostCentre != null).Select(CostCentre => CostCentre.Id);
var property = profileExample.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(x => x.Name != keyName).First();
var collection = ((IEnumerable)property.GetValue(profileExample, null)).AsQueryable();
var collectionType = property.PropertyType.GetGenericArguments()[0];
var collectionTypeName = collectionType.Name;
//BeginWhere
var parameter = Expression.Parameter(collectionType, collectionTypeName);
var profileExampleWhere = Expression.Lambda(
Expression.NotEqual(parameter, Expression.Constant(null)),
parameter);
var profileExampleWhereCall = Expression.Call(typeof(Enumerable),
"Where",
new Type[] { collectionType },
collection.Expression,
profileExampleWhere);
//EndWhere
//BeginSelect
var profileExampleSelect = Expression.Lambda(Expression.PropertyOrField(parameter, keyName),
parameter);
var profileExampleSelectCall = Expression.Call(typeof(Enumerable),
"Select",
new Type[] { collectionType, keyType },
profileExampleWhereCall,
profileExampleSelect);
var Ids = Expression.Lambda(profileExampleSelectCall).Compile().DynamicInvoke();
//EndSelect
//End var Ids = profileExample.CostCenters.Where(CostCentre => CostCentre != null).Select(CostCentre => CostCentre.Id);
return ((IEnumerable)Ids).Cast<Int64>();
}
public partial class Profile
{
public virtual Int64 Id { get; set; }
public virtual ICollection<CostCentre> CostCenters { get; set; }
}
public partial class CostCentre
{
public virtual Int64 Id { get; set; }
}
public static Profile profileExample
{
get
{
return new Profile()
{
Id = 1,
CostCenters = new List<CostCentre>() { new CostCentre() { Id = 2 } }
};
}
}
public static IList<Profile> Set
{
get
{
return new List<Profile>() { new Profile() { Id = 1,
CostCenters = new List<CostCentre>() { new CostCentre() { Id = 1 },
new CostCentre() { Id = 2 } }
},
new Profile() { Id = 2,
CostCenters = new List<CostCentre>() { new CostCentre() { Id = 2 },
new CostCentre() { Id = 3 } }
},
new Profile() { Id = 3,
CostCenters = new List<CostCentre>() { new CostCentre() { Id = 3 } }
} };
}
}
}
}
Since Any is a Generic Method you need to create it for a specific type. The method below gets the Any<T> method from the Enumerable type.
public static MethodInfo GetAnyExtensionMethod(Type forType)
{
MethodInfo method =
typeof(Enumerable).GetMethods()
.First(m => m.Name.Equals("Any") &&
m.GetParameters().Count() == 2);
return method.MakeGenericMethod(new[] { forType });
}
Its solved with help of Mads from MS
class Program
{
static void Main(string[] args)
{
//var Ids = profileExample.CostCenters.Where(CostCentre => CostCentre != null).Select(CostCentre => CostCentre.Id);
var Ids = AboveLambdaConvertedToExpressionTree(profileExample);
//var result = Set.AsQueryable().Where(Profile => Profile.CostCenters.Select(CostCentre => CostCentre.Id).Any(Id => Ids.Contains(Id))).ToList();
var id = Expression.Parameter(typeof(long), "Id");
var costCentre = Expression.Parameter(typeof(CostCentre), "CostCentre");
var profile = Expression.Parameter(typeof(Profile), "Profile");
var selectLambda = Expression.Lambda(Expression.PropertyOrField(costCentre, "Id"), costCentre);
var selectCall = Expression.Call(typeof(Enumerable),
"Select",
new Type[] { typeof(CostCentre), typeof(long) },
Expression.PropertyOrField(profile, "CostCenters"),
selectLambda);
//var id2 = Expression.Parameter(typeof(long), "Id");
var containsCall = Expression.Call(typeof(Enumerable),
"Contains",
new Type[] { typeof(long) },
Expression.Constant(Ids),
id);
var anyLambda = Expression.Lambda(containsCall, id);
var anyCall = Expression.Call(typeof(Enumerable),
"Any",
new Type[] { typeof(long) },
selectCall,
anyLambda);
var whereLambda = Expression.Lambda(anyCall, profile);
var callExpression = Expression.Call(typeof(Queryable),
"Where",
new Type[] { typeof(Profile) },
Set.AsQueryable().Expression,
whereLambda);
var result = Expression.Lambda(callExpression).Compile().DynamicInvoke();
}