LINQ to Entities parameter constructor - c#

I've looked around for multiple solutions, but non seemed to work. I aim using a LINQ query to get data and populate an object, however; when I try to assign result to the a ReponseObj I get
Only parameterless constructors and initializers are supported in LINQ to Entities.
The constructor for ObjVO is parameterless.
public static ApiResponseObject<ObjVO> GetObjVO(int ID)
{
ApiResponseObject<ObjVO> response = new ApiResponseObject<ObjVO>();
Context ctx = new Context();
var myQuery = from cb in ctx.tblBlock
join eve in ctx.tblEvent on cb.eventID equals eve.eventID
where cb.BlockID == ID
select new ObjVO
{
Id = cb.BlockID,
Name = cb.BlockHeadline,
TotalTYProjectedSales = cb.totalTYProjectedSale.Value,
StoreTYProjectedSales = cb.storeTYProjectedSale.Value,
SiteTYProjectedSales = cb.storeTYProjectedSale.Value,
ModifiedBy = cb.LAST_UPD_USER_ID,
LastModifiedDate = cb.LAST_UPD_TS,
StoreUnitsOnHand = cb.storeUnitsOnHand.Value,
AssignedCutsCount = 0,
BlockHeadline = cb.contentBlockHeadline,
BelongsToLockedAd = false,
ProductLevel = 1,
SiteAvailability = false,
};
response.responseData = myQuery.FirstOrDefault();
}

This might be because EF cannot translate your query into a SQL statement.
See this for reference.

Related

Implicit ViewModel generation from LINQ?

In my project I have a GenericImageViewModel which is used by many entities.
Example of getting the ASP User Entity:
var query = UserRepository.Get(Id).Select(a => new TRDIdenityViewModel
{
FirstName = a.UserProfile.FirstName,
LastName = a.UserProfile.LastName,
NickName = a.UserProfile.NickName,
ProfileImage = a.UserProfile.ProfileImage
});
The ProfileImage is the GenericImageViewModel and has an implicit operator as follows:
public static implicit operator TRDGenericImageViewModel(TRDImage image)
{
return new TRDGenericImageViewModel
{
Id = image.Id,
AspectRatio = image.Ratio,
Url = image.Url,
};
}
If I run the query Entity Framework throws an exception:
"Unable to cast the type 'TRDImage' to type 'TRDGenericImageViewModel'. LINQ to Entities only supports casting EDM primitive or enumeration types."
If I create the GenericImageViewModel manually for each ViewModel everything is running fine:
var query = UserRepository.Get(Id).Select(a => new TRDIdenityViewModel
{
FirstName = a.UserProfile.FirstName,
LastName = a.UserProfile.LastName,
NickName = a.UserProfile.NickName,
ProfileImage = new TRDGenericImageViewModel {
Id = a.UserProfile.ProfileImage.Id,
AspectRatio = a.UserProfile.ProfileImage.Ratio,
Url = a.UserProfile.ProfileImage.Url,
},
});
But in this case I have to copy and paste the TRDGenericImageViewModel generation in every ViewModel and thats not the way it should goes. If something changed I have to modify all related classes.
So is there a way to avoid this exception?
Using .AsEnumerable() prior lambda is not possible due to selects later in that query.
var query = UserRepository
.Get(Id)
.AsEnumerable()
.Select(a => new TRDIdenityViewModel
{
FirstName = a.UserProfile.FirstName,
LastName = a.UserProfile.LastName,
NickName = a.UserProfile.NickName,
ProfileImage = new TRDGenericImageViewModel
{
Id = a.UserProfile.ProfileImage.Id,
AspectRatio = a.UserProfile.ProfileImage.Ratio,
Url = a.UserProfile.ProfileImage.Url,
},
Statistics = new TRDUserStatisticsViewModel
{
PostCount = a.Posts.Count(),
CommentCount = a.Comments.Count(),
ImageCount = a.Images.Count(),
VideoCount = a.Videos.Count(),
VoteCount = a.PostVotes.Count(),
}
});
When calling .AsEnumerable() only the entities included by the Include statement are counted. But if the user has more than 1000 Posts and 10.000 Votes the query is a data nightmare.

Parameterize DocumentDB query with IN clause

I have a query somewhat like the following which I'm trying to parameterize:
List<string> poiIDs = /*List of poi ids*/;
List<string> parameterNames = /*List of parameter names*/;
string inClause = string.Join(",", parameterNames);
string query = string.Format("SELECT c.id AS poiID, c.poiName, c.latitude, c.longitude FROM c WHERE c.clusterName = #clusterName AND c.id IN ({0}) AND c.deleted = false", inClause);
IQueryable<POI> queryResult = Client.CreateDocumentQuery<POI>(Collection.SelfLink, new SqlQuerySpec
{
QueryText = query,
Parameters = new SqlParameterCollection()
{
new SqlParameter("#clusterName", "POI"),
// How do I declare the dynamically generated parameters here
// as new SqlParameter()?
}
});
How do I declare the dynamically generated parameters as new SqlParameter() for the Parameters property of SqlQuerySpec in order to create my document query?
You can create dynamic parameterized query like this:
// DocumentDB query
// POINT TO PONDER: create the formatted query, so that after creating the dynamic query we'll replace it with dynamically created "SQL Parameter/s"
var queryText = #"SELECT
us.id,
us.email,
us.status,
us.role
FROM user us
WHERE us.status = #userStatus AND us.email IN ({0})";
// contain's list of emails
IList<string> emailIds = new List<string>();
emailIds.Add("a#gmail.com");
emailIds.Add("b#gmail.com");
#region Prepare the query
// simple parameter: e.g. check the user status
var userStatus = "active";
var sqlParameterCollection = new SqlParameterCollection { new SqlParameter("#userStatus", userStatus) };
// IN clause: with list of parameters:
// first: use a list (or array) of string, to keep the names of parameter
// second: loop through the list of input parameters ()
var namedParameters = new List<string>();
var loopIndex = 0;
foreach (var email in emailIds)
{
var paramName = "#namedParam_" + loopIndex;
namedParameters.Add(paramName);
var newSqlParamter = new SqlParameter(paramName, email);
sqlParameterCollection.Add(newSqlParamter);
loopIndex++;
}
// now format the query, pass the list of parameter into that
if (namedParameters.Count > 0)
queryText = string.Format(queryText, string.Join(" , ", namedParameters));
// after this step your query is something like this
// SELECT
// us.id,
// us.email,
// us.status,
// us.role
// FROM user us
// WHERE us.status = #userStatus AND us.email IN (#namedParam_0, #namedParam_1, #namedParam_2)
#endregion //Prepare the query
// now inject the parameter collection object & query
var users = Client.CreateDocumentQuery<Users>(CollectionUri, new SqlQuerySpec
{
QueryText = queryText,
Parameters = sqlParameterCollection
}).ToList();
The following gives you a SQL query, you can then run in your DocumentDB Collection, to get the Documents by their IDs.
var query = $"SELECT * FROM p WHERE p.id IN ('{string.Join("', '", arrayOfIds)}')";
The DocumentDB SDK doesn't support parameterized IN queries.
Judging from the SO thread in the comment above, SQL does not either. As mentioned in the other thread, you can use LINQ as a workaround.
Why not use the ArrayContains method? Here is an example in node
sqlQuery = {
query: 'SELECT * FROM t WHERE ARRAY_CONTAINS(#idList, t.id)',
parameters: [
{
name: '#idList',
value: ['id1','id2','id3'],
},
],
};

get associated records in ms dynamics crm

Hi to get associated records from campaignlist_association in ms crm 2013. Tried tons of different variations.
This is last one:
System.Guid campaignId = ((EntityReference)entity.Attributes["regardingobjectid"]).Id;
var list = (from c in EntityCon.CampaignSet
join l in EntityCon.ListSet on c.campaignlist_association equals l.campaignlist_association
where c.CampaignId == campaignId select c).First();
The error message
The type of one of the expressions in the join clause is incorrect. Type inference failed in the call to 'Join'
indicates that the types of the properties used with the equals expression must match, e.g. that they are both Int32 or Guid.
Make sure that the type l.campaignlist_association is the same as the type c.campaignlist_association.
I would use code as follows to get the associated entity records. Change the column set as per your requirement.
private EntityCollection GetAssociatedEntityItems(string relationshipName, string relatedEntityName, string entityName, Guid entityId)
{
EntityCollection result = null;
QueryExpression query = new QueryExpression();
query.EntityName = relatedEntityName;
query.ColumnSet = new ColumnSet(false);
Relationship relationship = new Relationship();
relationship.SchemaName = relationshipName;
relationship.PrimaryEntityRole = EntityRole.Referencing;
RelationshipQueryCollection relatedEntity = new RelationshipQueryCollection();
relatedEntity.Add(relationship, query);
RetrieveRequest request = new RetrieveRequest();
request.RelatedEntitiesQuery = relatedEntity;
request.ColumnSet = new ColumnSet(true);
request.Target = new EntityReference
{
Id = entityId,
LogicalName = entityName
};
RetrieveResponse response = (RetrieveResponse)serviceProxy.Execute(request);
RelatedEntityCollection relatedEntityCollection = response.Entity.RelatedEntities;
if (relatedEntityCollection.Count > 0)
{
if (relatedEntityCollection.Values.Count > 0)
{
result = (EntityCollection)relatedEntityCollection.Values.ElementAt(0);
}
}
return result;
}

method x has no supported translation to SQL when use a static class

I am using MVC platform and a jqGrid in the views. below is the part of controller code return json to the grid
IQueryable<CalendarViewModel> callendars =
from call in (new KYTCDataContext()).Calendars
where call.AcademicYear == id
select Matcher.Calendar(call);
if (jqGridParameters._search != false)
{
callendars = callendars.Where(jqGridParameters.WhereClause);
}
if (jqGridParameters.sidx != null)
callendars = callendars.OrderBy(
jqGridParameters.sidx.Substring(8) + " " + jqGridParameters.sord.ToLower());
var count = callendars.Count();
int pageIndex = jqGridParameters.page;
the Matcher is a static class. below is the used method of the class
public static class Matcher
{
public static CalendarViewModel Calendar(Calendar call)
{
return new CalendarViewModel
{
ID = call.ID,
Name = call.Name,
StartDate = call.StartDate,
EndDate = call.EndDate,
AcademicYear = call.AcademicYear
};
}
}
at the line
var count = callendars.Count();
i recieve this error:
Method 'KYTC.Models.CalendarViewModel Calendar(KYTC.Data.Calendar)' has no supported translation to SQL.
but when I change the LINQ query to this:
IQueryable<CalendarViewModel> callendars =
from call in (new KYTCDataContext()).Calendars
where call.AcademicYear == id
select new CalendarViewModel
{
ID = call.ID,
Name = call.Name,
StartDate = call.StartDate,
EndDate = call.EndDate,
AcademicYear = call.AcademicYear
};
my code is running well.
what is wrong with my class definition?
Nothing is wrong with your class definition. The problem is that you simply can't call arbitrary functions in Linq-to-SQL (or EntityFramework) queries. Only a handful of predefined methods can be translated into SQL syntax. Your final method is the correct way of returning CalendarViewModel objects from a query.
However, you could also do this:
public static Expression<Func<Calendar, CalendarViewModel>> CalendarExpression()
{
return c => new CalendarViewModel
{
ID = c.ID,
Name = c.Name,
StartDate = c.StartDate,
EndDate = c.EndDate,
AcademicYear = c.AcademicYear
};
}
var calendarExpr = Match.CalendarExpression();
IQueryable<CalendarViewModel> callendars =
(from call in (new KYTCDataContext()).Calendars
where call.AcademicYear == id
select call)
.Select(calendarExpr);

Linq to Entity Left Outer Join

I have an Entity model with Invoices, AffiliateCommissions and AffiliateCommissionPayments.
Invoice to AffiliateCommission is a one to many, AffiliateCommission to AffiliateCommissionPayment is also a one to many
I am trying to make a query that will return All Invoices that HAVE a commission but not necessarily have a related commissionPayment. I want to show the invoices with commissions whether they have a commission payment or not.
Query looks something like:
using (var context = new MyEntitities())
{
var invoices = from i in context.Invoices
from ac in i.AffiliateCommissions
join acp in context.AffiliateCommissionPayments on ac.affiliateCommissionID equals acp.AffiliateCommission.affiliateCommissionID
where ac.Affiliate.affiliateID == affiliateID
select new
{
companyName = i.User.companyName,
userName = i.User.fullName,
email = i.User.emailAddress,
invoiceEndDate = i.invoicedUntilDate,
invoiceNumber = i.invoiceNumber,
invoiceAmount = i.netAmount,
commissionAmount = ac.amount,
datePaid = acp.paymentDate,
checkNumber = acp.checkNumber
};
return invoices.ToList();
}
This query above only returns items with an AffiliateCommissionPayment.
I'm not sure if EF supports this (nor am I sure if you are using EF2 or EF4), but this is the solution in Linq2Sql so it might be worth trying:
using (var context = new MyEntitities())
{
var invoices = from i in context.Invoices
from ac in i.AffiliateCommissions
join acp in context.AffiliateCommissionPayments on ac.affiliateCommissionID equals acp.AffiliateCommission.affiliateCommissionID into acp_join
from acp_join_default in acpg.DefaultIfEmpty()
where ac.Affiliate.affiliateID == affiliateID
select new
{
companyName = i.User.companyName,
userName = i.User.fullName,
email = i.User.emailAddress,
invoiceEndDate = i.invoicedUntilDate,
invoiceNumber = i.invoiceNumber,
invoiceAmount = i.netAmount,
commissionAmount = ac.amount,
datePaid = acp.paymentDate,
checkNumber = acp.checkNumber
};
return invoices.ToList();
}
The main change here is the into acpg after your join, and the DefaultIfEmpty line.
It's almost always a mistake to use join in LINQ to SQL and LINQ to Entities.
Guessing that the association from AffiliateCommission to AffiliateCommissionPayment is called Payment, you can just do:
using (var context = new MyEntitities())
{
var invoices = from i in context.Invoices
from ac in i.AffiliateCommissions
where ac.Affiliate.affiliateID == affiliateID
select new
{
companyName = i.User.companyName,
userName = i.User.fullName,
email = i.User.emailAddress,
invoiceEndDate = i.invoicedUntilDate,
invoiceNumber = i.invoiceNumber,
invoiceAmount = i.netAmount,
commissionAmount = ac.amount,
datePaid = (DateTime?) ac.Payment.paymentDate,
checkNumber = (int?) ac.Payment.checkNumber
};
return invoices.ToList();
}
LINQ to SQL and LINQ to Entities will both coalesce nulls. The casts are necessary because the inferred type will be based on the type of AffiliateCommissionPayment.paymentDate, which might not be nullable. If it is, you don't need the cast.

Categories