Concatenating two fields in LINQ select - c#

I have a dropdownlist, ddCourse, that I'm populating with the following LINQ query:
var db = new DataClasses1DataContext();
ddCourse.DisplayMember = "COURSE_TITLE";
ddCourse.ValueMember = "COURSE_ID";
ddCourse.DataSource = db.COURSE_MASTERs.OrderBy(c => c.COURSE_TITLE)
.Select(c => new { c.COURSE_ID, c.COURSE_TITLE })
.ToList();
There's another field, though, that I'd like to concatenate to the COURSE_TITLE field in my selection. So, I'd like my selection to look like:
.Select( c => new {c.COURSE_ID, c.CIN + " " + c.COURSE_TITLE})
The only problem is that this, apparently, isn't how it's done. I'm basically wanting to join c.CIN with c.COURSE_TITLE (and have a space in the middle). Can someone offer me some pointers on how to accomplish this?
The reason I want to do this is that, right now, the only thing appearing in the dropdownlist is the course title. I'd like to have the course ID number (CIN) concatenated to it when it displays.
EDIT: For clarification, I'm using Linq-to-SQL.

use this
.Select( c => new {c.COURSE_ID, COURSE_TITLE =string.Format("{0} {1}" ,c.CIN ,c.COURSE_TITLE)})

You need to name your anonymous members:
.Select( c => new {COURSE_ID = c.COURSE_ID, COURSE_TITLE = c.CIN + " " + c.COURSE_TITLE})

Write your Select like this:
.Select( c => new {c.COURSE_ID, COURSE_TITLE = c.CIN + " " + c.COURSE_TITLE})
Anonymous types need to have their column names specified, in case they cannot be inferred.
For c.COURSE_ID C# is smart enough to generate a member called COURSE_ID in the anonymous type. For the expression c.CIN + " " + c.COURSE_TITLE it cannot.

Related

How to turn array into quote and comma delimited string for sql?

I have a list I want to pass into SQL but they must be single quote and comma delimited.
So List = a b c
But I need a string = 'a','b','c'
How can I accomplish this in a concise manner?
Something like this I think but can't see within LINQ how to add to beginning and end:
String.Join(",", arr.Select(p => p.ToString()).ToArray())
Maybe something along the lines of:
String.Join(",", arr.Select(p=> "'" + p.ToString() + "'").ToArray());
// or is p already a string
String.Join(",", arr.Select(p => "'" + p + "'").ToArray());
You can do this:
String.Join(",", arr.Select(p => $"'{p.ToString()}'").ToArray());
And that will put the ' on either side of p.ToString() for each element.
Use an ORM that supports the following construction:
string[] items = GetItems();
var query = db.Rows.Where(row => items.Contains(row.ColumnName));
This way, you do not open yourself to sql injection by constructing strings to hand to the database yourself.
You should also be careful if your source data contains "'" in which case you need to escape the "'". Try this:
var arr = new [] { "a'c", "b" };
var output = String.Join(",", arr.Select(p => $"'{p.Replace("'", "''")}'"));
That gives "'a''c','b'".

Linq query returns the same names even though they should be different

I am new to EF6 and I have set up the Chinook database and gotten it working with SqlLite .NET provider on .NET Framework 4.0.
When I execute the following query, it executes without problems but the track names are all the same. They should be different because they have different track IDs and I have looked up those track IDs and they have different names.
var result = context.Playlists.Include(p => p.Tracks)
.Where(p => p.Name == "Brazilian Music")
.SelectMany(p => p.Tracks);
foreach(var p in result)
{
Console.WriteLine(p.Playlist.Name + ", " + p.TrackId + ", " + p.Track.Name);
}
Appreciate any help.
Here is the output of my result:
Console Output:
Your entities are not correct.
If Playlist has a TrackId this means that a play list only can have one track.
Your output shows that you have many play lists with the same name. Track should have PlaylistId instead but it's hard giving an exact answer without seing the entities.
OK, I tried another approach using joins to the junction table and now it gives the correct result
var result = from p in context.Playlists
join pt in context.PlaylistTracks on p.PlaylistId equals pt.PlaylistId
join t in context.Tracks on pt.TrackId equals t.TrackId
where p.Name == "Brazilian Music"
select new { PlaylistName = p.Name, TrackId = t.TrackId, TrackName = t.Name };
foreach (var p in result)
{
Console.WriteLine(p.PlaylistName + ", " + p.TrackId + ", " + p.TrackName);
}
I have checked the junction table POCO and I don't see any problems with it.
I still don't understand why the first approach isn't working.

Use linq to sort on changed field

I have a linq query using C# and would like to sort on a changed field. The field is a partial date field defined in the table as YYYYMM. However, I want it displayed in my repeater as,
MM/YYYY but need to sort it as YYYYMM. Below is the code and GrantMonthID is the field in question. The repeater displays the data in MM/YYYY order.
Thank you.
var linqQuery = from nn in grantsReceivedDetailList
where (nn.ArrearAuditID == Convert.ToInt32(AdminBasePage.ArrearAuditId))
select
new
{
nn.GrantsReceivedID,
nn.PayeeMPINumber,
Firstname = participantRepository.GetParticipantDetailsbyMemberParticipantIndex(Convert.ToInt32(nn.PayeeMPINumber)).FirstName + " " +
participantRepository.GetParticipantDetailsbyMemberParticipantIndex(Convert.ToInt32(nn.PayeeMPINumber)).LastName,
nn.IVANumber,
GrantMonthID = nn.GrantMonthID.ToString().Substring(4, 2) + "/" + nn.GrantMonthID.ToString().Substring(0, 4),
nn.GrantAmount,
nn.Comments
};
linqQuery = linqQuery.OrderByDescending(y => y.GrantMonthID);
// Execute the linq query and databind
grantListRepeater.DataSource = linqQuery;
grantListRepeater.DataBind();
Just create a property to sort on, and a property to bind to:
var query = from x in someList
select new
{
SortField = FormatForSort(x.Field),
DisplayField = FormatForDisplay(x.Field)
};
query = query.OrderBy(x => x.SortField);
Alternately, select it by the Date, and format it how you want in the repeater instead of using LINQ since this is more of a View concern.
Add to your anonymous type field which will contain original database date:
var linqQuery =
from nn in grantsReceivedDetailList
where (nn.ArrearAuditID == Convert.ToInt32(AdminBasePage.ArrearAuditId))
select new {
nn.GrantsReceivedID,
nn.PayeeMPINumber,
Firstname = participantRepository.GetParticipantDetailsbyMemberParticipantIndex(Convert.ToInt32(nn.PayeeMPINumber)).FirstName + " " +
participantRepository.GetParticipantDetailsbyMemberParticipantIndex(Convert.ToInt32(nn.PayeeMPINumber)).LastName,
nn.IVANumber,
GrantMonthID = nn.GrantMonthID.ToString().Substring(4, 2) + "/" +
nn.GrantMonthID.ToString().Substring(0, 4),
nn.GrantAmount,
nn.Comments,
GrantMonthIdOriginal = nn.GrantMonthID // this field
};
And sort by this field:
linqQuery = linqQuery.OrderByDescending(y => y.GrantMonthIdOriginal);
grantListRepeater.DataSource = linqQuery;
grantListRepeater.DataBind();

Building SQL IN statement from listbox control

I'm trying to build a SQL query using StringBuilder and I've become stuck trying to do part of the WHERE clause.
I have a list box with a bunch of values and allows multiple selection. I need to iterate through the selected items and put then in an IN statement like...
WHERE SOME_FIELD IN ('Value','NextValue','AnotherValue')
so far I've written the code like this...
if (lstSalesGroup.SelectedItem != null)
{
selectQuery.Append("AND SALES_GROUP IN (");
foreach (ListItem item in lstSalesGroup.Items)
{
if (item.Selected)
selectQuery.Append("'" + item.Value + "',");
}
selectQuery.Append(")");
}
I need to test if the item is the last in the loop so that it doesn't put on the "," before the closing ")".
How can I do this? Or if there's a better way to build this part of the query please do suggest, I am still learning, we all have to start somewhere! :)
Eventually this will be a query for a part search.
Thanks in advance
Couple of ways for doing that.
You can use string.TrimEnd to remove the extra comma from the string or you can create a new string using string.Join like
string InPartQuery = string.Join(",", lstSalesGroup.Items
.Cast<ListItem>()
.Where(t => t.Selected)
.Select(r => "'" + r.Value + "'"));
You could use String.Join with some Linq
For clearity I've put the code in variables.
if (lstSalesGroup.SelectedItem != null)
{
var queryStr = "AND SALES_GROUP IN ({0})";
var selectedItemValues = (from itm in lstSalesGroup.Items.Cast<ListItem>()
where itm.Selected
select String.Format("'{0}'", itm));
selectQuery.Append(String.Format(queryStr, String.Join(",", selectedItemValues)));
}
Try using linq
selectQuery.Append("AND SALES_GROUP IN (");
selectQuery.Append(string.Join(",", lstSalesGroup.Items.Select(i => "'" + i.Value + "'")));
selectQuery.Append(")");
This will solve your problem, but you have a problem with SQL injection here. I would strongly advice you to use parameters in your query.
Dim s As String = "'"
For i = 0 To ListBox1.Items.Count - 1
s = s & ListBox1.Items.Item(i) & "','"
Next
Try this:
if (lstSalesGroup.SelectedItem != null)
{
selectQuery.Append("AND SALES_GROUP IN (");
var local = lstSalesGroup.Items.Where(c => c.Selected)
.Select(c => "'"+c.Value+"'")
.Aggregate((c,n) => c+ ", "+n);
selectQuery.Append(local);
selectQuery.Append(")");
}
Look at this example for more info on the .Aggragate(...) method

ToString() method not supported

I am trying to create a selectlist in c#. My code :
var ceremonies = db.Ceremonies;
var Ceremonies =
from c in ceremonies
select new SelectListItem
{
Text = c.Name + "_" + c.Date,
Value = c.Id.ToString()
};
But here i am getting exception something like ToString() method not supported. Whats the problem ?
Your query is being transformed into SQL - but the call to ToString can't be handled properly. Generally the simplest way of fixing this is to effectively split the query into the part that needs to be done in the database, then switch to LINQ to Objects via AsEnumerable:
var ceremonies = db.Ceremonies
.Select(c => new { c.Name, c.Date, c.Id }
.AsEnumerable()
.Select(c => new SelectListItem {
Text = c.Name + "_" + c.Date,
Value = c.Id.ToString()
});
As an aside, declaring two local variables which vary only by case gives pretty nasty readability.

Categories