This code builds without problems but fails when executed:
var query =
_db.STEWARDSHIP
.OrderByDescending(r => r.VisitDate)
.Where(r => SiteId == null || r.SiteAssoc.Id == iSiteId)
.Where(r => r.MarkedForDeletion == false)
.Select(r => new SearchResults(r.Id,
r.SiteAssoc.Name,
r.VisitDate,
r.VisitTypeValAssoc.Description));
The error message is:
Only parameterless constructors and initializers are supported in LINQ to Entities.
What am I doing wrong here? I must pass info to the constructor to build the SearchResults objects. Is there a way to do this or do I have to make this a 2-step thing where I get the results and then iterate over the results to create the new objects?
UPDATE:
Changing the select to this fixes the issue:
.Select(r => new SearchResults(){Id = r.Id,
Name = r.SiteAssoc.Name,
VisitDate = r.VisitDate,
VisitType = r.VisitTypeValAssoc.Description});
Try this
.OrderByDescending(r => r.VisitDate)
.Where(r => SiteId == null || r.SiteAssoc.Id == iSiteId)
.Where(r => r.MarkedForDeletion == false)
.Select(r => new SearchResults()
{
ID = Ir.Id,
Name = r.SiteAssoc.Name,
VisitDate = r.VisitDate,
Description = r.VisitTypeValAssoc.Description
});
Entities can be created outside of queries and inserted into the data
store using a DataContext. You can then retrieve them using queries.
However, you can't create entities as part of a query.
See this post Explicit construction of entity type '###' in query is not allowed.
LINQ doesn't allow the explicit construction of objects within the select statements.
Related
I am trying to generate a List<Object> using Where clause with properties from a different List<Object>. I know that I could use a .Include(), similar to a SQL join if I were using Entity Framework but I am not using Entity Framework so I don't think it would work. I have:
List<Problem> problems = MethodToCallDbAndGenerateList(); //ado.net
problems = problems.Where(x => x.Property1 == "value").ToList();
//remaining logic
List<Solved> solved = MethodToCallDb()
.Where(x => x.SolvedId == problems.ProblemId)
.ToList();
//error happens in Where(...problems.ProblemId);
//List<Problem> does not contain a definition for ProblemId
The error says the List<Problem> does not contain ProblemId but I do have that property in my class. So I am unsure of why I am getting that error.
How can I generate my List<Solved> based on filtered results from
.Where(x => x.SolvedId == problems.SolvedId);
Using LINQ to Objects, you can use the Enumerable.Join method to create a join between two List<T>s and just return the matching members:
List<Problem> problems = MethodToCallDbAndGenerateList()
.Where(x => x.Property1 == "value")
.ToList();
List<Solved> solved = MethodToCallDb()
.Join(problems, s => s.SolvedId, p => p.ProblemId, (s,p) => s)
.ToList();
However, if there are a lot of problems and solved, or if you frequently check the same list of problems, or if you are only creating problems to use in the join, you'd be better off creating a HashSet:
var problemIDs = problems.Select(p => p.ProblemId).ToHashSet();
List<Solved> solved = MethodToCallDb()
.Where(s => problemIDs.Contains(s.SolvedId))
.ToList();
NOTE: If you are only creating problems to use in the join, better to skip creating the List<Problem> and just do:
var problemIDs = MethodToCallDbAndGenerateList()
.Where(x => x.Property1 == "value")
.Select(p => p.ProblemId)
.ToHashSet();
The code below gave the above error at point where it try to enter the foreach. I have checked the database table and also did a select using the parameters that was passed when I stepped through the code and it returned something.
var propertyItems = from x in _context.Db.tbl_BranchProperty
where x.BranchId == BranchId && x.ClientId == clientId
select x;
foreach (var propertyItem in propertyItems)
{
I discovered the error was as a result of the difference between the properties of the entity tbl_BranchProperty and tbl_BranchProperty table columns.
It seems that you have wrapped your context object and made it static, try to create new object and initialize it properly then user your query like that.
yourContext db = new yourContext();
var propertyItems = db.tbl_BranchProperty
.Where(x => x.BranchId == BranchId && x.ClientId == clientId)
.Select(x => x)
.ToList();
I am using LINQ to retrieve Account type entities from Microsoft Dynamics CRM Online. I am unable to filter the list for a particular formatted value. I have the correct value, but am receiving zero records.
I'm creating my connection like this:
var connection = new CrmConnection("CRMOnline");
connection.ProxyTypesEnabled = true;
CrmOrganizationServiceContext _context = new CrmOrganizationServiceContext(connection);
I've tried:
List<Account> items = _context.CreateQuery<Account>()
.Where( c => ((OptionSetValue)c["new_accreditationstatus"]).Equals(7))
.ToList();
and
List<Account> items = _context.CreateQuery<Account>()
.Where( c => c.GetFormattedAttributeValue("new_accreditationstatus") == "7"
.ToList();
and
List<Account> items = _context.CreateQuery<Account>()
.Where( c => c["new_accreditationstatus"] == "7"
.ToList();
The last on throws a System.Format exception.
Filters on normal properties, i.e. .Where(c => c.AccountNumber.StartsWith("2010")) work perfectly fine.
You can only get access to the _____Set entities when generating the early-bound CRM file (look into crmsvcutil.exe/Xrm.cs online) and creating an early-bound derivative of CrmOrganizationServiceContext (commonly called XrmServiceContext). You can see the available constructors in the early-bound file.
So if you know the (int) value of the OptionSetValue in advance (7, in this case), you can just use this value as one of the arguments in the Where clause, as you've stated elsewhere:
.Where( c => c.new_AccreditationStatus.Value == 7)
EDIT (try this):
var list = _context.AccountSet.Where(c =>
c.FormattedValues["new_accreditationstatus"] == "7").ToList();
Another great question, but unfortunately, I think this will represent another failure/"limitation" of the Linq provider, which doesn't mention anything about FormattedValues as one of the permitted uses of the Where clause, though it is permitted as an item in the Select clause.
The actual values for OptionSetValues are stored in the StringMap entity, and incidentally enough, you can access the StringMap entity via Linq. An example is as follows.
// This query gets one permissible value for this entity and field.
var actualValue = _context.CreateQuery("stringmap")
.Where(x => x.GetAttributeValue<string>("attributename") == "new_accreditationstatus")
.Where(x => x.GetAttributeValue<int>("value") == "7")
.Where(x => x.GetAttributeValue<int>("objecttypecode") == Account.EntityTypeCode)
.Select(x => x.GetAttributeValue<string>("value"))
.Single();
However, trying to build on this with a subquery and a version of your original query, as in the below, results in an exception, also below.
var actualValues = _context.CreateQuery("stringmap")
.Where(x => x.GetAttributeValue<string>("attributename") == "new_accreditationstatus")
.Where(x => x.GetAttributeValue<int>("objecttypecode") == Xrm.Account.EntityTypeCode);
// This (modified) query uses the StringMap values from the previous query in
// a subquery, linking to the int (attributevalue) value that
// new_accreditationstatus represents.
List<Account> items = _context.CreateQuery<Account>()
.Where(c => actualValues
.Where(x => x.GetAttributeValue<int>("attributevalue") == c.new_accreditationstatus.Value)
.Select(x => x.GetAttributeValue<string>("attributevalue"))
.Single() == "7")
.ToList();
...throws an exception.
Privilege Type Read not defined on entity 'StringMap'.
Which is of course frustrating, because somehow, Linq allows you to query the string map in the first query.
So you'll have to first query the StringMap entity for the AttributeValue that corresponds to "7", then use that value in a new query that references that value as follows:
var actualValue = _context.CreateQuery("stringmap")
.Where(x => x.GetAttributeValue<string>("attributename") == "new_accreditationstatus")
.Where(x => x.GetAttributeValue<int>("value") == "7")
.Where(x => x.GetAttributeValue<int>("objecttypecode") == Account.EntityTypeCode)
.Select(x => x.GetAttributeValue<string>("attributevalue"))
.Single();
List<Account> items = _context.CreateQuery<Account>()
.Where(c => c.new_accreditationstatus = new OptionSetValue(actualValue)
.ToList();
If I can ever find a way to do all of this in one query, I will definitely edit and repost.
Have you seen the crmsvcutil extension that will generate enumerations for optionsets?
I'm have a SQL statement which I am trying to transform in a LINQ statement...
SELECT DISTINCT mc.*
FROM ManufractorCategories mc
WHERE mc.Active = 'true'
AND mc.Folder = 'false'
AND (mc.Id not in (SELECT Category_id FROM Manufractor_Category
WHERE Manufractor_id = 3));
That's my last, not working LINQ statement
(IQueryable<object>)db.ManufractorCategories
.Where(o => o.Active == active)
.Where(o => o.Folder == folder)
.Select(i => new { i.Id, i.Folder }).Except(db.Manufractor_Categories.Where(t => t.Manufractor_id == id).Select(t => new { t.Category_id })).Distinct();
I've tried the whole Sunday on that, but the Except statement won't work.
Thanks in advances for any help!
The Except method requires two sets of the same type - this means that you would have to select objects of type ManufractorCategory in the nested query as well as in the outer query - then it would select all categories that are in the first one and not in the second one.
An easier alternative is to use the Contains method to check whether the current ID is in a list of IDs that you want to filter. The following should work:
var q =
db.ManufractorCategories
.Where(o => o.Active == active)
.Where(o => o.Folder == folder)
.Select(i => new { i.Id, i.Folder })
.Where(o =>
!db.Manufractor_Categories
.Select(t => t.Manufractor_id)
.Contains(o.Id)
.Distinct();
And a simplified version using query syntax:
var q =
from o in db.ManufractorCategories
where o.Active == active && o.Folder == folder &&
db.Manufractor_Categories
.Select(t => t.Manufractor_id)
.Contains(o.Id)
select new { i.Id, i.Folder };
The Except statement is going to get a list of objects with the Category_id property. However, you're query has a result that contains objects with the Id and Folder properties. The query will most likely be unable to see where these objects are equal, and so, the Except clause won't take effect.
I am trying something that i not really sure but i want to ask here if it s possible.
Is it able to be done ?
public IQueryable<Info> GetInfo(int count, byte languageId)
{
return db.Info.SelectMany(i => i.LanguageInfo)
.Where(l => l.Language.id == languageId)
.Select(l => new Info { AddDate = l.Info.AddDate,
Description = l.Description,
EntityKey = l.Info.EntityKey,
id = l.Info.id,
Title = l.Title,
ViewCount = l.Info.ViewCount }
)
.OrderByDescending(i => i.id)
.Take(count);
}
When this method is executed i got an error
The entity or complex type
'GuideModel.Info' cannot be
constructed in a LINQ to Entities
query.
Does it mean "not possible" ?
Thank you
The error essentially indicates that the Entity Framework doesn't know how to create an Info object, since it is not bound to a table object. (Put another way, the Select call on the IQueryable cannot be translated into equivalent SQL.) You could perform the Select projection on the client via:
public IQueryable<Info> GetInfo(int count, byte languageId)
{
return db.Info.SelectMany(i => i.LanguageInfo)
.Where(l => l.Language.id == languageId)
.Take(count)
.AsEnumerable()
.Select(l => new Info { AddDate = l.Info.AddDate,
Description = l.Description,
EntityKey = l.Info.EntityKey,
id = l.Info.id,
Title = l.Title,
ViewCount = l.Info.ViewCount }
)
.OrderByDescending(i => i.id);
}
It is possible to use Select(l => new ...), but not with an Entity type. You need to use an anonymous type or a POCO type with a parameterless constructor. Entity types are "special" because of the way they interact with the ObjectContext. You can select them, but not new them up in a query.
The code below worked for me. Here "SearchTerm" is a complex type. Thanks Jason :)
var lstSynonym = TechContext.TermSynonyms
.Where(p => p.Name.StartsWith(startLetter))
.AsEnumerable()
.Select(u => new SearchTerm
{
ContentId = u.ContentId,
Title = u.Name,
Url = u.Url
});