LINQ where condition with string operations - linq

I get this error when that linq code runs. I try many string methods like concat,join,etc. But LINQ doesn't permit string operations. Finally error is runtime error.
ERROR: System.NotSupportedException: 'System.String Format(System.String, System.Object, System.Object)'
public List<ItemEntity> GetItems(List<string> codeList)
{
return ExecuteCrud(session =>
{
return (from Item in session.Query<ItemEntity>()
where (codeList.Contains(Item.code) || codeList.Contains($"{Item.Id.ToString().PadLeft(10, '0')}-{ Item.ItemId.ToString().PadLeft(12, '0')}"))
select Item).ToList();
});
}

Related

How to get data from two tables using web api

I want to get data from two tables using web api, but I'm receiving an error.
Here is my code:
public List<tblEmpTask> GettblEmpTasks()
{
var q = (from n in db.tblEmpTasks
join c in db.tblEmployees on n.intEmpCode equals c.intEmpCode
select new
{
n.strTaskName,
n.dtStart,
c.strEmployeeName,
}).ToList();
return q;
}
Here is the error that I'm receiving:
The type of one of the expressions in the join clause is incorrect. Type inference failed in the call to 'Join'.
and please note that I am using web api. Looking forward to solve this issue.
when selecting an anonymous the function should return List<object>
or instead
use a type to return value such as-
class myType{
string TaskName, //assuming type as string
string dtStart, //assuming type as string
string EmployeeName //assuming type as string
}
and in LinQ query something like -
select new myType{ TaskName=n.strTaskName, dtStart=n.dtStart, EmployeeName=c.strEmployeeName}
and return as List<myType>

How to dynamically order by certain entity properties in Entity Framework 7 (Core)

I have a project where the front-end JavaScript specifies a list of columns to order by.
Then in the back-end I have multi-layer application. Typical scenario
Service layer (the service models' (DTO) properties match whatever the client-side wants to order by)
Domain layer (it exposes repository interfaces to access persisted objects)
ORM layer (it implements the repository and it uses Entity Framework 7 (a.k.a Entity Framework Core) to access a SQL Server database)
Please note that System.Linq.Dynamic IS NOT supported for DNX Core v5.0 or .NET Platform v5.4 so I cannot use that library.
I have the following implementation in my Things repository:
public async Task<IEnumerable<Thing>> GetThingsAsync(IEnumerable<SortModel> sortModels)
{
var query = GetThingsQueryable(sortModels);
var things = await query.ToListAsync();
return things;
}
private IQueryable<Thing> GetThingsQueryable(IEnumerable<SortModel> sortModels)
{
var thingsQuery = _context.Things
.Include(t => t.Other)
.Where(t => t.Deleted == false);
// this is the problematic area as it does not return a valid queryable
string orderBySqlStatement = GetOrderBySqlStatement(sortModels);
thingsQuery = thingsQuery.FromSql(orderBySqlStatement);
return thingsQuery ;
}
/// this returns something like " order by thingy1 asc, thingy2 desc"
private string GetOrderBySqlStatement(IEnumerable<SortModel> sortModels)
{
IEnumerable<string> orderByParams = sortModels.Select(pair => { return pair.PairAsSqlExpression; });
string orderByParamsConcat = string.Join(", ", orderByParams);
string sqlStatement = orderByParamsConcat.Length > 1 ? $" order by {orderByParamsConcat}" : string.Empty;
return sqlStatement;
}
and this is the object that contains a column name and a order by direction (asc or desc)
public class SortModel
{
public string ColId { get; set; }
public string Sort { get; set; }
public string PairAsSqlExpression
{
get
{
return $"{ColId} {Sort}";
}
}
}
This approach tries to mix a SQL statement with whatever Entity creates for the previous queryable. But I get a:
Microsoft.Data.Entity.Query.Internal.SqlServerQueryCompilationContextFactory:Verbose: Compiling query model: 'from Thing t in {value(Microsoft.Data.Entity.Query.Internal.EntityQueryable`1[MyTestProj.Data.Models.Thing]) => AnnotateQuery(Include([t].DeparturePort)) => AnnotateQuery(Include([t].ArrivalPort)) => AnnotateQuery(Include([t].Consignments))} where (([t].CreatorBusinessId == __businessId_0) AndAlso (Convert([t].Direction) == __p_1)) select [t] => AnnotateQuery(QueryAnnotation(FromSql(value(Microsoft.Data.Entity.Query.Internal.EntityQueryable`1[MyTestProj.Data.Models.Thing]), " order by arrivalDate asc, arrivalPortCode asc", []))) => Count()'
Microsoft.Data.Entity.Query.Internal.SqlServerQueryCompilationContextFactory:Verbose: Optimized query model: 'from Thing t in value(Microsoft.Data.Entity.Query.Internal.EntityQueryable`1[MyTestProj.Data.Models.Thing]) where (([t].CreatorBusinessId == __businessId_0) AndAlso (Convert([t].Direction) == __p_1)) select [t] => Count()'
Microsoft.Data.Entity.Query.Internal.QueryCompiler:Error: An exception occurred in the database while iterating the results of a query.
System.InvalidOperationException: The Include operation is not supported when calling a stored procedure.
at Microsoft.Data.Entity.Query.ExpressionVisitors.RelationalEntityQueryableExpressionVisitor.VisitEntityQueryable(Type elementType)
at Microsoft.Data.Entity.Query.ExpressionVisitors.EntityQueryableExpressionVisitor.VisitConstant(ConstantExpression constantExpression)
at System.Linq.Expressions.ConstantExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.Data.Entity.Query.ExpressionVisitors.ExpressionVisitorBase.Visit(Expression expression)
at Microsoft.Data.Entity.Query.EntityQueryModelVisitor.ReplaceClauseReferences(Expression expression, IQuerySource querySource, Boolean inProjection)
at Microsoft.Data.Entity.Query.EntityQueryModelVisitor.CompileMainFromClauseExpression(MainFromClause mainFromClause, QueryModel queryModel)
at Microsoft.Data.Entity.Query.RelationalQueryModelVisitor.CompileMainFromClauseExpression(MainFromClause mainFromClause, QueryModel queryModel)
at Microsoft.Data.Entity.Query.EntityQueryModelVisitor.VisitMainFromClause(MainFromClause fromClause, QueryModel queryModel)
at Remotion.Linq.Clauses.MainFromClause.Accept(IQueryModelVisitor visitor, QueryModel queryModel)
at Remotion.Linq.QueryModelVisitorBase.VisitQueryModel(QueryModel queryModel)
at Microsoft.Data.Entity.Query.EntityQueryModelVisitor.VisitQueryModel(QueryModel queryModel)
at Microsoft.Data.Entity.Query.RelationalQueryModelVisitor.VisitQueryModel(QueryModel queryModel)
at Microsoft.Data.Entity.Query.Internal.SqlServerQueryModelVisitor.VisitQueryModel(QueryModel queryModel)
at Microsoft.Data.Entity.Query.EntityQueryModelVisitor.CreateAsyncQueryExecutor[TResult](QueryModel queryModel)
at Microsoft.Data.Entity.Storage.Database.CompileAsyncQuery[TResult](QueryModel queryModel)
at Microsoft.Data.Entity.Query.Internal.QueryCompiler.<>c__DisplayClass19_0`1.<CompileAsyncQuery>b__0()
at Microsoft.Data.Entity.Query.Internal.CompiledQueryCache.GetOrAddAsyncQuery[TResult](Object cacheKey, Func`1 compiler)
at Microsoft.Data.Entity.Query.Internal.QueryCompiler.CompileAsyncQuery[TResult](Expression query)
at Microsoft.Data.Entity.Query.Internal.QueryCompiler.ExecuteAsync[TResult](Expression query, CancellationToken cancellationToken)
Exception thrown: 'System.InvalidOperationException' in EntityFramework.Core.dll
Exception thrown: 'System.InvalidOperationException' in mscorlib.ni.dll
Exception thrown: 'System.InvalidOperationException' in mscorlib.ni.dll
Microsoft.AspNet.Diagnostics.Entity.DatabaseErrorPageMiddleware:Verbose: System.InvalidOperationException occurred, checking if Entity Framework recorded this exception as resulting from a failed database operation.
Microsoft.AspNet.Diagnostics.Entity.DatabaseErrorPageMiddleware:Verbose: Entity Framework recorded that the current exception was due to a failed database operation. Attempting to show database error page.
Microsoft.Data.Entity.Storage.Internal.SqlServerConnection:Verbose: Opening connection 'Server=(localdb)\mssqllocaldb;Database=SpeediCargo;Trusted_Connection=True;MultipleActiveResultSets=true'.
Microsoft.Data.Entity.Storage.Internal.SqlServerConnection:Verbose: Closing connection 'Server=(localdb)\mssqllocaldb;Database=SpeediCargo;Trusted_Connection=True;MultipleActiveResultSets=true'.
Microsoft.Data.Entity.Storage.Internal.SqlServerConnection:Verbose: Opening connection 'Server=(localdb)\mssqllocaldb;Database=SpeediCargo;Trusted_Connection=True;MultipleActiveResultSets=true'.
Microsoft.Data.Entity.Storage.Internal.SqlServerConnection:Verbose: Closing connection 'Server=(localdb)\mssqllocaldb;Database=SpeediCargo;Trusted_Connection=True;MultipleActiveResultSets=true'.
Microsoft.Data.Entity.Storage.Internal.SqlServerConnection:Verbose: Opening connection 'Server=(localdb)\mssqllocaldb;Database=SpeediCargo;Trusted_Connection=True;MultipleActiveResultSets=true'.
Microsoft.Data.Entity.Storage.Internal.RelationalCommandBuilderFactory:Information: Executed DbCommand (0ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT OBJECT_ID(N'__EFMigrationsHistory');
Microsoft.Data.Entity.Storage.Internal.SqlServerConnection:Verbose: Closing connection 'Server=(localdb)\mssqllocaldb;Database=SpeediCargo;Trusted_Connection=True;MultipleActiveResultSets=true'.
Microsoft.Data.Entity.Storage.Internal.SqlServerConnection:Verbose: Opening connection 'Server=(localdb)\mssqllocaldb;Database=SpeediCargo;Trusted_Connection=True;MultipleActiveResultSets=true'.
Microsoft.Data.Entity.Storage.Internal.RelationalCommandBuilderFactory:Information: Executed DbCommand (0ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
It seems it's not possible to mix SQL for the order by part with the rest of the linq query?
Or the problem is that I am not prefixing the columns with the [t] and Entity is unable to understand what are those columns?
In any case, is there any example or recommendation on how to achieve what I want with Entity 7 and the core .net framework?
FromSql definitely cannot be used to mix SQL. So as usual with dynamic queries, you have to resort to System.Linq.Expressions.
For instance, something like this:
public static class QueryableExtensions
{
public static IQueryable<T> OrderBy<T>(this IQueryable<T> source, IEnumerable<SortModel> sortModels)
{
var expression = source.Expression;
int count = 0;
foreach (var item in sortModels)
{
var parameter = Expression.Parameter(typeof(T), "x");
var selector = Expression.PropertyOrField(parameter, item.ColId);
var method = string.Equals(item.Sort, "desc", StringComparison.OrdinalIgnoreCase) ?
(count == 0 ? "OrderByDescending" : "ThenByDescending") :
(count == 0 ? "OrderBy" : "ThenBy");
expression = Expression.Call(typeof(Queryable), method,
new Type[] { source.ElementType, selector.Type },
expression, Expression.Quote(Expression.Lambda(selector, parameter)));
count++;
}
return count > 0 ? source.Provider.CreateQuery<T>(expression) : source;
}
}
And then:
var thingsQuery = _context.Things
.Include(t => t.Other)
.Where(t => t.Deleted == false)
.OrderBy(sortModels);

Unable to cast object of type CRM 2013 Plugin

I have a Synchronous plugin that runs when any opportunity create/delete/update. And in Plugin if any error comes i have made a function which insert log into database.
In table one field if EntityId, so i am writing the following code :
foreach (PropertyBagEntry entry in (IEnumerable<PropertyBagEntry>)context.InputParameters.Values)
{
DynamicEntity entity = (DynamicEntity)entry.Value;
foreach (Property property in (IEnumerable<Property>)entity.Properties)
{
if (property.GetType().Name == "KeyProperty")
{
str4 = ((Key)entity.Properties[property.Name]).Value.ToString();
break;
}
}
}
In str4 i am getting EntityId of current process.
But it gives one exception very frequently :
Unhandled Exception: System.InvalidCastException: Unable to cast object of type
'ValueCollection[System.String,System.Object]'
to type 'System.Collections.Generic.IEnumerable`1[Microsoft.Crm.Sdk.PropertyBagEntry]'
And i have identified that the following line is giving error
foreach (PropertyBagEntry entry in (IEnumerable)context.InputParameters.Values)
Anyone have idea to convert this line in another way ?
My understanding is that you want to get the GUID of current record, if this is the case then you can do it as:
public void Execute(IServiceProvider serviceProvider)
{
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
try
{
if (context.MessageName == "Create" || context.MessageName == "Update")
{
if (context.InputParameters.Contains("Target") && (context.InputParameters["Target"] is Entity))
{
Entity currentEntity = (Entity) context.InputParameters["Target"];
Guid currentRecordGuid = currentEntity.Id;
}
}
}
catch (Exception ex)
{
}
}
I believe the type of that collection varies from one message to another. If you are looking to get the Id of the record within a plugin, this helper function may come in handy:
public static Guid GetEntityIdFromContext(IPluginExecutionContext context)
{
string messageName = context.MessageName;
if (context.PrimaryEntityId != Guid.Empty)
{
return context.PrimaryEntityId;
}
else if (messageName == "Create")
{
return new Guid(context.OutputParameters["id"].ToString());
}
else
{
return context.PrimaryEntityId;
}
}
If that doesn't help, would you mind providing the message that causes the error?
If
Unhandled Exception: System.InvalidCastException: Unable to cast
object of type 'ValueCollection[System.String,System.Object]' to type
'System.Collections.Generic.IEnumerable`1[Microsoft.Crm.Sdk.PropertyBagEntry]'
is truly your error, than your issue is not with line
foreach (Property property in (IEnumerable<Property>)entity.Properties)
but with line:
foreach (PropertyBagEntry entry in (IEnumerable<PropertyBagEntry>)context.InputParameters.Values)
The type of context.InputParameters.Values is not castable to an IEnumerable

How to make list of ICollection

Model class:
public class MonthlySalesOrders : BaseNopEntityModel
{
public ICollection<Nop.Core.Domain.Orders.OrderItem> Categories { get; set; }
}
Controller Action
private PagedList.IPagedList<MonthlySalesOrders> orderByDateAdded()
{
var ord = _orderService.SearchOrders();
var daylyOrderReport = (from o in ord.AsEnumerable()
group o by new { Quarter = ((o.CreatedOnUtc.CompareTo(DateTime.UtcNow.AddDays(-7)))) } into orGrp
select new MonthlySalesOrders
{ Categories = (ICollection<Nop.Core.Domain.Orders.OrderItem>)orGrp.Select(c => c.OrderItems)
})
return daylyOrderReport.ToPagedList(1, 10);
}
From above "controller action" I have used linq query to select orderlist from "orGrp group", and into "Model class" I have declared a public ICollection<Nop.Core.Domain.Orders.OrderItem> Categories { get; set; }, so when I build and ran the above code it displays following error messages.
Unable to cast object of type 'WhereSelectEnumerableIterator2[Nop.Core.Domain.Orders.Order,System.Collections.Generic.ICollection1[Nop.Core.Domain.Orders.OrderItem]]' to type 'System.Collections.Generic.ICollection`1[Nop.Core.Domain.Orders.OrderItem]'.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.InvalidCastException: Unable to cast object of type 'WhereSelectEnumerableIterator2[Nop.Core.Domain.Orders.Order,System.Collections.Generic.ICollection1[Nop.Core.Domain.Orders.OrderItem]]' to type 'System.Collections.Generic.ICollection`1[Nop.Core.Domain.Orders.OrderItem]'.
Source Error:
Line 2374: var daylyOrderReport = (from o in ord.AsEnumerable()
Line 2375: group o by new { Quarter = ((o.CreatedOnUtc.CompareTo(DateTime.UtcNow.AddDays(-7)))) } into orGrp
Line 2376: select new MonthlySalesOrders
Line 2377: {
Line 2378: Year = orGrp.First().CreatedOnUtc.Year.ToString(),
and I want get category list from three level nested reference from orGrp like Categories =(ICollection<Nop.Core.Domain.Orders.OrderItem>) orGrp.Select(gb => gb.OrderItems.Select(s => s.Product.ProductManufacturers))
so please help me how can I do this.
You can use the ToList function which returns an IList which implements ICollection. Also, it looks like c.OrderItems is an enumerable of items, not a single item. If this is the case then you'll want to flatten list returned with SelectMany.
orGrp.SelectMany(c => c.OrderItems).ToList()

NHibernate 3.3 Linq calling user defined function with bit parameter and bit result

I'm extending the NHibernate Linq provider and i wish to call a user defined that has both bit parameter[s] and return type.
Here's the SQL user defined function signature:
FUNCTION f_DocumentsFreeTextSearch
(
#docId int,
#searchString varchar(8000),
#searchTitle bit
)
RETURNS bit
Here's the "fake" extension method used for Linq usage:
public static class DialectExtensions
{
public static bool FreeText(this Document doc, string searchString, bool searchTitle)
{
return false;
}
}
Here's my LinqToHqlGeneratorsRegistry
public sealed class ExtendedLinqToHqlGeneratorsRegistry : DefaultLinqToHqlGeneratorsRegistry
{
public ExtendedLinqToHqlGeneratorsRegistry()
{
DialectExtensions.FreeText(null, null, true)),
new FreeTextGenerator());
}
}
And here's my generator:
public class FreeTextGenerator : BaseHqlGeneratorForMethod
{
public FreeTextGenerator()
{
SupportedMethods = new[]
{
ReflectionHelper.GetMethodDefinition(() => DialectExtensions.FreeText(null, null, true))
};
}
#region Overrides of BaseHqlGeneratorForMethod
public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection<Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
{
return treeBuilder.MethodCall("dbo.f_documentsfreetextsearch", arguments.Select(a => visitor.Visit(a).AsExpression()).ToArray());
}
#endregion
}
This is the desired usage:
[TestMethod]
public void CanFreeText()
{
var query = SessionHolder.Current.Query<Document>();
var list = query.Where(d => d.FreeText("giorno", true)).ToList();
}
First problem: the above code causes an InvalidCastException:
Test method App.Tests.NHMapping.CanFreeText threw exception:
System.InvalidCastException: Unable to cast object of type
'NHibernate.Hql.Ast.HqlMethodCall' to type
'NHibernate.Hql.Ast.HqlBooleanExpression'.
Solved this way (not elegant but it works):
[TestMethod]
public void CanFreeText()
{
var query = SessionHolder.Current.Query<Document>();
var list = query.Where(d => d.FreeText("giorno", true) == true).ToList();
}
Now NHibernate executes the query, but the generated SQL is wrong:
Test method App.Tests.NHMapping.CanFreeText threw exception:
NHibernate.Exceptions.GenericADOException: could not execute query [
select [...] from dbo.DOCUMENTS document0_ where case when
dbo.f_documentsfreetextsearch(document0_.IDDOCUMENT, #p0, #p1=1) then
1 else 0 end=#p2 ] Name:p1 - Value:giorno Name:p2 - Value:True
Name:p3 - Value:True [SQL: select [...] from dbo.DOCUMENTS document0_
where case when dbo.f_documentsfreetextsearch(document0_.IDDOCUMENT,
#p0, #p1=1) then 1 else 0 end=#p2] --->
System.Data.SqlClient.SqlException: Incorrect syntax near '='.
Please not that the function call in the generated SQL has #p1=1 as third parameter, and that the WHERE clause is an inline CASE instead of
dbo.f_documentsfreetextsearch(document0_.IDDOCUMENT, #p0, #p1) = 1
as i expected.
If i change in my C# code the bool parameter and return type into Int32, everything just work well (but still not very elegant).
Any idea of how to get desired syntax to work?
Thanks in advance
Claudio
PS: sorry for lots of code and errors' text :P
seems you hit the same bug NH-2839 as i did when using usertype for boolean property. not much you can do about it now until this is fixed.

Resources