This question already has answers here:
LINQ query on a DataTable
(22 answers)
Closed 1 year ago.
I am trying to convert the following LINQ code from VB.NET to C#, which is performed on the DataTable "tvp_dtl". Followed by VB code.
Dim query
query = From row In tvp_dtl
Group row By dataGroup = New With {
Key .Tmall_txn_no = row.Field(Of String)("Tmall_txn_no"),
Key .stock_code = row.Field(Of String)("stock_code"),
Key .ItemNameLocalLang = row.Field(Of String)("ItemNameLocalLang"),
Key .ItemUnitPrice = row.Field(Of String)("ItemUnitPrice"),
Key .itemTotalAmount = row.Field(Of String)("itemTotalAmount")
} Into Group
Select New With {
.Tmall_txn_no = dataGroup.Tmall_txn_no,
.stock_code = dataGroup.stock_code,
.ItemNameLocalLang = dataGroup.ItemNameLocalLang,
.ItemUnitPrice = dataGroup.ItemUnitPrice,
.itemTotalAmount = dataGroup.itemTotalAmount,
.SumAmount = Group.Sum(Function(x) Integer.Parse(x.Field(Of String)("ItemNumber")))}
Here is the version I wrote in C#
var query = from row in tvp_dtl
group row by new
{
row.Tmall_txn_no = row.Field<string>("Tmall_txn_no"),
row.stock_code = row.Field<string>("stock_code"),
row.ItemNameLocalLang = row.Field<string>("ItemNameLocalLang")
} into dataGroup
select new
{
Tmall_txn_no = dataGroup.Field<string>("Tmall_txn_no"),
stock_code = dataGroup.Field<string>("stock_code"),
ItemNameLocalLang = dataGroup.Field<string>("ItemNameLocalLang"),
ItemUnitPrice = dataGroup.Field<string>("ItemUnitPrice"),
itemTotalAmount = dataGroup.Field<string>("itemTotalAmount"),
SumAmount = dataGroup.Sum(x => int.Parse(x.Field<string>("ItemNumber") * int.Parse(x.Field<string>("QtyPerSet"))))
};
But I think it is incorrect. Besides I got this error when using "tvp_dtl"
Could not find the implementation of the query pattern for source
type "DataTable". Group By not found
DataTable isn't an IEnumerable and even worse it doesn't provide the method required by the compiler to behave as an enumerable.
public class DataTable : MarshalByValueComponent, IListSource, ISupportInitializeNotification, ISupportInitialize, ISerializable, IXmlSerializable
Luckily there's an extension method that fixes that.
Try this:
var query =
from row in tvp_dtl.AsEnumerable()
Related
This question already has answers here:
linq select a random row
(6 answers)
Closed 3 years ago.
I want to select 1 random record. I use LINQ to SQL for my query, but im not really familiar with these (I know normal SQL queries better)
This is my code:
public void giveRand()
{
var query = (from Performance in db.Performances.OrderBy(c => Guid.NewGuid()).Take(1)
join Stage in db.Stages on Performance.stage_id equals Stage.stage_id
join Artist in db.Artists on Performance.artist_id equals Artist.artist_id
select new AllClass(db)
{
all_performance_id = Performance.performance_id,
all_starttime = Performance.starttime,
all_endtime = Performance.endtime,
all_artistname = Artist.name,
all_stagename = Stage.name,
all_artistdesc = Artist.description,
all_stagedesc = Stage.description
}).Single();
App.Current.Properties["timestart"] = query.all_starttime;
App.Current.Properties["timeened"] = query.all_endtime;
App.Current.Properties["namea"] = query.all_artistname;
App.Current.Properties["names"] = query.all_stagename;
App.Current.Properties["desca"] = query.all_artistdesc;
App.Current.Properties["descs"] = query.all_stagedesc;
}
I dont know whats wrong.
I'd follow the advice from the comment and rewrite a bit the query.
But, to answer your question, you can use Skip(random)+Take(1):
Random r = new Random();
int n = // number of records
var record = ... /* linq query */ .Skip(r.Next(0, n)).Take(1)
I have four tables, with Date data type for the fields startingDate, EndingDate, and ApplyingDate.
I am using ADO.net Entity Framework.
I have written the following query to get the results, but I am getting the dates with the time, and I want only the date part.
I have used EntityFunctions.TuncateTime, but I am still getting same results.
Could anyone please suggest me, how to Get the date only ?
var leaveList = (from application in db.tbl_ApplicationData
join employee in db.tbl_EmployeeDetails
on application.UserName equals employee.UserName
join leaveType in db.tbl_LeaveType
on application.LeaveTypeId equals leaveType.LeaveTypeId
join status in db.tbl_Status
on application.ApplicationStatusId equals status.StatusId
where application.UserName == "100083"
select new
{
EmployeeName = employee.EmployeeName,
LeaveTypeID = leaveType.LeaveTypeName,
StartingDate = EntityFunctions.TruncateTime(application.StartingDate),
EndingDate = EntityFunctions.TruncateTime(application.EndingDate),
AppliedDate = EntityFunctions.TruncateTime(application.ApplyingDate),
NoOfDays = application.NoOfDays,
LeavePurpose = application.LeavePurpose,
LeaveStatus = status.StatusName
});
If your entity model is a System.DateTime, you can just use the DateTime methods when you are using your object:
select new {
EndingDate = application.EndingDate
};
var myValue = leaveList.EndingDate.Date;
Or if you want a string:
leaveList.EndingDate.ToShortDateString()
I'm trying to the the value of a lookup field in SharePoint using Linq and a collection of SPListItem - something like this:
int totalDepts = (from SPListItem itm in hourEntries select ((SPFieldLookupValue)itm["Level1"]).LookupValue).Distinct().Count();
But that doesn't seem to work (and it strikes me as missing some steps)
Has anyone done this before?
I wasn't able to figure out to do it directly in the Linq query, so I ended up creating WorkHoursEntries object, and populating it with all my SPListItems
List<WorkHourEntry> workHourEntries = new List<WorkHourEntry>();
foreach (SPListItem hourEntry in hourItems)
{
//Collect entries that are in the current Fiscal Year reporting period
if (fiscalYearMonths.Contains(hourEntry["Reporting_x0020_Month"].ToString()))
{
WorkHourEntry curEntry = new WorkHourEntry();
string Level1 = (string)hourEntry["Level1"];
SPFieldLookupValue val = new SPFieldLookupValue(Level1);
curEntry.organization = val.LookupValue;
SPFieldCalculated cf = (SPFieldCalculated)hourEntry.Fields["WECSCHours"];
curEntry.WECSCHours = cf.GetFieldValueForEdit(hourEntry["WECSCHours"]);
workHourEntries.Add(curEntry);
}
}
This allowed me to run Linq queries directly on the WorkHourEntry collection
var uniqueDeptNames = (from itm in workHourEntries select itm.organization).Distinct().ToArray();
AdomdCommand cmd = new AdomdCommand(commandText, conn);
CellSet cs = cmd.ExecuteCellSet();
var result = from a in cs
select new
{...};
Is it possible to use LINQ to read from CellSet? I have tried using DataTable instead of CellSet but it's much slower (Example: I took a query that using DataTable takes ~45 sec to execute, but using CellSet it takes ~5 sec).
The error I get when trying to use LINQ:
Could not find an implementation of the query pattern for source type
'Microsoft.AnalysisServices.AdomdClient.CellSet'. 'Select' not found.
UPDATE:
I have tried Enrico's suggestion and so far it doesn't return any errors. Next problem is how to read a value from a cell. Here's what I have tried so far:
var result = from cell in cs.Cells.Cast<Cell>()
select new searchResultsPolicy
{
PolicyNumber = ...
InsuredName = cell.Field<string>("[Insured].[DBA Name].[DBA Name].[MEMBER_CAPTION]"),
Agency = cell.Field<string>("[Agency].[Agency Name].[Agency Name].[MEMBER_CAPTION]"),
Market = cell.Field<string>("[Market].[Market Name].[Market Name].[MEMBER_CAPTION]"),
Revenue = String.Format("{0:#,##0}", cell.Field<double?>("[Measures].[Revenue]") ?? 0),
Premium = String.Format("{0:#,##0}", cell.Field<double?>("[Measures].[Premium]") ?? 0)
};
The reason you get that error is that the CellSet class in itself doesn't implement IEnumerable<T>, which is required by LINQ.
Try executing the LINQ query over the CellSet.Cells property instead. That will return a CellCollection object, which implements IEnumerable. From there you can easily convert it to an IEnumerable<T> by using the Enumerable.Cast<T> method.
AdomdCommand cmd = new AdomdCommand(commandText, conn);
CellSet cs = cmd.ExecuteCellSet();
var result = from cell in cs.Cells.Cast<Cell>()
select new
{ ... };
See also:
Retrieving Data Using the CellSet
I have an object with two different integer properties in it, and I'm trying to get a a new object in Linq to Entities, combining two integer properties from the same object as concatenated strings, as follows
List<DateRange> collection = (from d in context.dates
select new DateRange
{
DateString = from s in context.Seasons
where s.SeasonID = d.DateID
select string.Format("{0} - {1}", s.StartYear, s.EndYear) }
).ToList<DateRange>();
The string concatenation of the years will not compile.
This will work in LINQ to Objects, provided that each object in objects is a class or struct containing "Number1" and "Number2" fields or properties:
var results = from o in objects
select string.Format("{0} - {1}", o.Number1, o.Number2);
(However, your original should work, as well....)
Assuming you are connecting to a database via LINQ to SQL/Entities, then the String.Format call will likely fail, as with those providers, the select clause is executed within the database. Not everything can be translated from C# into SQL.
To convert your database results into a string like you want to, the following should work:
var temp = (
from d in context.dates
from s in context.Seasons
where s.SeasonID == d.DateID
select new { s.StartYear, s.EndYear }
).ToList(); // Execute query against database now, before converting date parts to a string
var temp2 =
from t in temp
select new DateRange
{
DateString = t.StartYear + " - " + t.EndYear
};
List<DateRange> collection = temp2.ToList();
EDIT:
I had an additional thought. The String.Format call is most likely the problem. I am not sure if it would work or not, but what about a plain-jane concat:
List<DateRange> collection =
(from d in context.dates
select new DateRange
{
DateString = from s in context.Seasons
where s.SeasonID = d.DateID
select s.StartYear + " - " + s.EndYear
}
).ToList<DateRange>();
Your original code works if you really want what you wrote. However, if your really want to get from
var objects = new MyObject[]{
new MyObject {Int1 = 1, Int2 = 2},
new MyObject {Int1 = 3, Int2 = 4}};
something like 1 - 2 - 3 - 4 you can write
var strings = objects.Select(o = > string.Format("{0} - {1}", o.Int1, o.Int2).ToArray();
var output = string.Join(" - ", strings);
using System.Data.Objects.SqlClient;
:
:
List<DateRange> collection = (from d in context.dates
select new DateRange
{
DateString = from s in context.Seasons
where s.SeasonID = d.DateID
select SqlFunctions.StringConvert((double)s.StartYear) + " - " +
SqlFunctions.StringConvert((double)s.EndYear)
}).ToList<DateRange>();
The StringConvert method gets converted into the proper conversion function when the LINQ statement is converted to SQL for execution on the server.