I'm having a problem of defining a data type for a list of grouped rows in LINQ to SQL.
I have a model MyDBModel with 2 properties
public class MyDBModel
{
public List<a_Cases_tbl> a_Cases { get; set; }
public List<b_Cases_tbl> b_Cases { get; set; }
}
In a controller I try to get data into this properties
MyDBDataContext myDb = new MyDBDataContext();
var listModel = new MyDBModel();
listModel.a_Cases=
(from t in myDb.a_cases_table
group t by new { t.Date, t.Name, t.Category, t.Code }
into myGroup
select new { myGroup.Key.Date, myGroup.Key.Name, myGroup.Key.Category, myGroup.Key.Code });
listModel.b_Cases =
(from t in myDb.B_cases_table
group t by new { t.Date, t.Name, t.Category, t.Code }
into myGroup
select new { myGroup.Key.Date, myGroup.Key.Name, myGroup.Key.Category, myGroup.Key.Code });
I get error:
Cannot implicitly convert type 'System.Collections.Generic.List < AnonymousType#1 > ' to 'System.Collections.Generic.List < MVC4.a_Cases_tbl > '
What will Data type for a_Cases should be if the result is going to be a List of Grouped by Multiple columns? Or how to define List < IGrouping < Tkey, Telement > > if the result is grouped by multiple fields of different types?
In your code you have created the list of anonymous type. You must tell compiler that you create the objects of appropriate type.
select new a_Cases_tbl{ myGroup.Key.Date, myGroup.Key.Name, myGroup.Key.Category, myGroup.Key.Code });
....
select new b_Cases_tbl{ myGroup.Key.Date, myGroup.Key.Name, myGroup.Key.Category, myGroup.Key.Code });
Related
I am trying to concatenate IQueryable where T can be different types.
So ((IQueryable<Person>)people).Concant((IQueryable<Account>)accounts).
I have created a structure like so:
public struct PerformanceStructure
{
public Entity Entity { get; set; }
public Entity Performance { get; set; }
}
I am building dynamic queries that follow this template:
var result = context.Accounts.Where(a => a.id == 1).Select(s => new PerformanceStructure { Entity = s });
result = result.Concat(context.Person.Where(p => p.id = 1).Select(s => new PerformanceStructure {Entity = s});
Execution looks like this:
var list = result.Skip(pageSize * (pageNumber - )).Take(pageSize);
When executing the query, I get the error Types in Union or Concat have different members assigned
What can I do to resolve this error but retrieve the two objects from that database?
In the end I want to paginate the query (thus the skip/take) based on some order.
I recently started experimenting with Raw SQL using Entity Framework, and I prefer it in some cases.
I would like to know if there is a way to grab relational entities:
Dosnt work:
var personNo = context.Person.SqlQuery("SELECT * FROM `Person` LIMIT 1").FirstOrDefault();
foreach(var Number in personNo.Phone) {
//never iterates
}
Works (but LINQ-to-Entities which I dont want in this case):
var personNo = context.Person.FirstOrDefault();
foreach(var Number in personNo.Phone) {
//iterate twice as it contains in the db
}
I tried a couple of different queries including
SELECT * FROM `Person` LEFT JOIN `Phone` ON (`Person`.ID = `Phone`.PersonID) LIMIT 1
What is the correct way to write the query on to recieve the list of Phone numbers? Is this possible?
You can do SQL to entities. I prefer this way when I have joins and group bys in them, and don't have permission to create a view.
First, create a class and add properties with the same names as the returned columns.
public class PersonWithAddress
{
public int Id { get; set; }
public String Name { get; set; }
public String Address { get; set; }
}
And the C# with parameters
MyEntity db = new MyEntity();
String sqlQuery = #"
SELECT Id, Name, Address
FROM Person p
JOIN Address a
ON a.Id = p.Id
WHERE Name = #Name
AND Address = #Address
";
String searchName = "Joe";
String address = "123 Something Lane";
DbRawSqlQuery<PersonWithAddress> results = db.Database.SqlQuery<PersonWithAddress>(
sqlQuery,
new SqlParameter("#Name", searchName),
new SqlParameter("#Address", address)
);
foreach(PersonWithAddress a in results)
{
}
You can list as many parameters as you want.
Wow this question's 2 years old. I didn't even realize that.
In Oracle it works well ......
Query for oracle is As Follows
Select distinct channel_id, position_id,datamonth,
percentile_cont(.9) within group (order by TRIM_PRE_ELIG_PAY)
over (partition by channel_id, position_id, datamonth) as TRIM_PRE_ELIG_PAY_90th_PERC
from Tablename
But for SQL Server, I'm getting an error. Here's the query for SQL Server 2008:
Select
distinct channel_id,
position_id, datamonth,
percentile_cont(.9) within group (order by TRIM_PRE_ELIG_PAY)
over (partition by channel_id) as TRIM_PRE_ELIG_PAY_90th_PERC
from table
ERROR: Select could not be parsed correctly. Output could not be
generated.
I got to know that it can work properly in SQL Server 2012 but need an alternative way in SQL Server 2008
Can anybody help...........
There is a workaround on the SQL Server Engine blog that applies to SQL Server 2005+
Unfortunately, it's quite long and convoluted: I'll leave you with the link rather than attempt to adapt it for your query...
You can create a CLR Aggregate function to implement the same. The only downfall is that you will have to re-arrange your query a bit. I implemented the percentile_cont using the CLR. Read here on how to create the CLR . Then you can use this code to get the same O/P as percentile_cont. Its a lot more easier than writing multiple statements.
You can definitely refine/tweak it a bit depending on your usage.
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.Collections.Generic;
[Serializable]
[Microsoft.SqlServer.Server.SqlUserDefinedAggregate(
Format.UserDefined,
IsInvariantToDuplicates = false,
IsInvariantToNulls = false,
IsInvariantToOrder = false,
MaxByteSize = 8000)]
public struct Percentile_Cont : IBinarySerialize
{
//Variables to hold the values;
private List<decimal> _list;
private decimal _percentile;
public void Init()
{
_list = new List<decimal>();
_percentile = new decimal();
}
public void Accumulate(SqlDecimal value,SqlDecimal percentile)
{
if (!value.IsNull)
{
_list.Add(value.Value);
_percentile = (decimal)percentile;
}
}
///
/// Merge the partially computed aggregate with this aggregate.
///
/// The other partial results to be merged
public void Merge(Percentile_Cont group)
{
this._list.AddRange(group._list.ToArray());
}
///
/// Called at the end of aggregation, to return the results.
///
/// The percentile of all inputted values
public SqlDecimal Terminate()
{
if (_list.Count == 0)
return SqlDecimal.Null;
_list.Sort();
if (_percentile < 0 || _percentile >= 1)
return SqlDecimal.Null;
var index =
(int) Math.Ceiling
(_percentile * _list.Count + 0.5m);
if(index > _list.Count)
{
index = index - 1;
}
return _list[index-1];
}
#region IBinarySerialize Members
public void Read(System.IO.BinaryReader binaryReader)
{
int cnt = binaryReader.ReadInt32();
this._list = new List<decimal>(cnt);
this._percentile = new decimal();
for (int i = 0; i < cnt; i++)
{
this._list.Add(binaryReader.ReadDecimal());
}
this._percentile = binaryReader.ReadDecimal();
}
public void Write(System.IO.BinaryWriter binaryWriter)
{
binaryWriter.Write(this._list.Count);
foreach (decimal d in this._list)
{
binaryWriter.Write(d);
}
binaryWriter.Write(_percentile);
}
#endregion
}
I have multiple queries that I'd like to union together, then compile the entire thing. The uncompiled query runs fine, but an "InvalidOperationException: Member access 'Int32 Id' of 'UserQuery+Foo' not legal on type 'System.Linq.IQueryable`1[UserQuery+Foo]." exception is thrown when the same query is compiled and run.
How do I fix this?
void Main()
{
var db = new MyDataContext( "..." );
Expression < Func < DataContext, int, IQueryable < Foo > > > queryExpression = (DataContext dc, int unused) =>
from ab in GetA(dc).Union( GetB(dc) )
group ab by new { ab.Id, ab.Name } into grp
select new Foo
{
Id = grp.Key.Id,
Name = grp.Key.Name,
Total = grp.Count()
};
var final = CompiledQuery.Compile ( queryExpression );
var result1 = queryExpression.Compile () (db, 0); // calling the original query works fine
var result2 = final (db, 0); // calling the compiled query throws an exception
}
public class Foo
{
public int Id { get; set; }
public string Name { get; set; }
public int Total { get; set; }
}
IQueryable<Foo> GetA( DataContext db )
{
return from b in db.GetTable<Bar>()
where b.IsActive
select new Foo { Id = b.Id, Name = b.Name };
}
IQueryable<Foo> GetB( DataContext db )
{
return from b in db.GetTable<Bar>()
where !b.IsActive
select new Foo { Id = b.Id, Name = b.Name };
}
EDIT
It looks like the union and grouping are irrelevant. Removing those elements from the query still causes an exception when compiled:
Expression < Func < DataContext, int, IQueryable < Foo > > > queryExpression = (DataContext dc, int unused) =>
from a in GetA(dc)
select new Foo
{
Id = a.Id,
Name = a.Name,
Total = 42
};
Replacing the call to GetA(dc) with dc.GetTable<Bar>() and adding the where clause fixes the issue.
So, is connecting separate queries together like this simply not possible for compiled queries?
EDIT #2
James' answer hit the nail on the head. Simplifying the query even further reveals the root problem:
Expression < Func < DataContext, int, IQueryable < Foo > > > queryExpression = (DataContext dc, int unused) =>
from a in GetA(dc)
select a;
This query throws NotSupportedException: Method 'System.Linq.IQueryable``1[UserQuery+Foo] GetA(System.Data.Linq.DataContext)' has no supported translation to SQL.
Pulling the call to GetA out into a separate variable assignment, then using that variable in the query throws a InvalidOperationException: Sequence contains more than one element exception.
I had the same issue and what seemed to do the trick for me was separating out an inline static method call that returned IQueryable<> so that I stored this deferred query into a variable and referenced that.
I think this is a bug in Linq to SQL but at least there is a reasonable workaround.
My guess is that the linq compiler doesn't understand the methods returning IQueryable.
To compile it, those methods would probably have to return some form of Expression<>.
I am using LINQ and am having a hard time understanding how I can make new "domain model" classes work within LINQ while querying across tables. I am using Linq to SQL, and C# in .NET 3.5.
Suppose I want an Extended Client class:
public class ExtendedClient
{
public int ID { get; set; }
public string Name { get; set; }
public string strVal { get; set; }
}
and in my data layer, I want to populate this from two tables (dc is my DataContext):
public ExtendedClient getExtendedClient(int clientID)
{
var c = dc.GetTable<tClient>();
var cs = dc.GetTable<tClientSetting>();
var q = from client in c
join setting in cs
on client.ClientID equals setting.ClientID
where client.ClientID == clientID
select new ExtendedClient { client, setting.strValue };
return q;
}
I am trying to return the row in the table tClient plus one extra column in tClientSetting.
The annoying errors I get are :
Cannot initialize type 'ExtendedClient' with a collection initializer because it does not implement 'System.Collections.IEnumerable'
and
Cannot implicitly convert type 'System.Linq.IQueryable' to 'ExtendedClient'. An explicit conversion exists (are you missing a cast?)
I realize this is a basic error, but I cannot determine how BEST to implement the IEnumerable because I cannot find an example.
Do I have to do this every time I want a specialized object? Thanks in advance.
public ExtendedClient getExtendedClient(int clientID)
{
var c = dc.GetTable<tClient>();
var cs = dc.GetTable<tClientSetting>();
var q = from client in c
join setting in cs
on client.ClientID equals setting.ClientID
where client.ClientID == clientID
select new ExtendedClient { ID = client.ClientID, Name = client.Name, strVal = setting.strValue };
return q.Single();
}
You'll have to do a similar thing every time you need to return a specialized object. If you don't need to return it, you don't have to specify the type and you won't need a special class. You could use anonymous types:
from client in c
join setting in cs
on client.ClientID equals setting.ClientID
where client.ClientID == clientID
select new { ID = client.ClientID, Name = client.Name, strVal = setting.strValue };
Why do you use a special type for this?
I think you can do client.Settings.strValue if you setup the Client-Settings relationship to create a property Client.Settings (instead of Settings.Client). And as far as I remember such configuration is possible in LINQ.