Give a Specific name to column in Linq - c#

I have following query,
var employees = from emp in this.DataWorkspace.v2oneboxData.me_employees
where emp.me_is_deleted.Value == false && emp.me_is_manager == true
select new{emp.me_first_name,emp.me_last_name,emp.me_pkey};
I want to give a specific name to emp.me_first_name column, just like we do in SQL Queries like:
select emp_first_Name as "First Name" from me_employees
how to do it in linq queries ???
also is it possible to combine firstName and lastname in select query in Linq ? just like we do in SQL Queries like :
select me_first_name + ' ' + me_last_name as 'Full Name' from me_employee
how can i achieve this task in linq?
Thanks

You can't make it First Name as that isn't a valid identifier, but you can use:
select new { FirstName = emp.me_first_name,
LastName = emp.me_last_name,
Key = emp.me_pkey };
Basically the property name in the anonymous type only defaults to whatever property you're using as the value - you can specify it yourself, but it has to be a valid C# identifier.
Or for the combination:
select new { FullName = emp.me_first_name + " " + emp.me_last_name,
Key = emp.me_pkey };

var list = fro e in emp
select new { FullName = e.Firstname + " " + e.LastName }
One of the example but its with the group by
Check more at : Learn SQL to LINQ (Visual Representation)

from emp in this.DataWorkspace.v2oneboxData.me_employees
where emp.me_is_deleted.Value == false && emp.me_is_manager == true
select new{FullName = String.Format("{0} {1}",emp.me_first_name, emp.me_last_name),emp.me_pkey};

Related

C# ASP.NET MVC 5 How to execute a raw query?

I am trying to execute a raw query using c#.
Here is what I have done
var accounts = conn.Database.SqlQuery<IEnumerable<string>>("SELECT TOP 1 a.* FROM zipcodes_to_accounts AS c " +
"INNER JOIN accounts AS a ON a.id = c.account_id " +
"WHERE c.zip_code = #p0 "+
"ORDER BY a.completed_ll + a.completed_cp ASC", zipcode).ToArray();
Then I want to take the first record and convert it to json object.
if (accounts.Count() > 0)
{
return JsonConvert.SerializeObject( accounts.First() );
}
But the query is giving me an error
The result type 'System.Collections.Generic.IEnumerable`1[System.String]' may not be abstract and must include a default constructor.
The accounts table has some columns that are varchar, datetime, integers. How can I get this query to work?
UPDATED
Converting the IEnumerable to list like advised in the answer it working. but now the JsonConvert is returning an empty object. Here is my current code
//getAccount
public string GetAccount()
{
string zipcode = StringHelpers.StringOrNull(Request["zip_code"]);
if (zipcode != null)
{
var accounts = conn.Database.SqlQuery<List<string>>("SELECT TOP 1 a.* FROM zipcodes_to_accounts AS c " +
"INNER JOIN accounts AS a ON a.id = c.account_id "+
"WHERE c.zip_code = #p0 "+
"ORDER BY a.completed_ll + a.completed_cp ASC", zipcode).ToList();
var firstAccount = accounts.FirstOrDefault();
if (firstAccount != null)
{
return JsonConvert.SerializeObject(firstAccount);
}
}
return "{}";
}
When I debug my code Here is what I see
Not sure what ORM you're using, but the warning is telling you that IEnumerable cannot be constructed as it's an interface. Therefore the SqlQuery method can't know what return type you're expecting.
Try replacing the generic constraint with a concrete type:
var accounts = conn.Database.SqlQuery<string>("SELECT TOP 1 a.* FROM zipcodes_to_accounts AS c " +
"INNER JOIN accounts AS a ON a.id = c.account_id " +
"WHERE c.zip_code = #p0 "+
"ORDER BY a.completed_ll + a.completed_cp ASC", zipcode).ToArray();
You're asking for a IEnumerable<string> which is an interface. You need to pick a class that implements IEnumerable such as a List

C# query using a generic Type

I am trying to make a generic function to do a database call (see code below). I have put the function in a separate solution, so that i can use it in different projects.
the line:
var data = d.Database.SqlQuery<T> (sql).First();
gives me the error:
Invalid object name 'VM_MailData'
(VM_MailData is the type I add as generic type T)
public static void ProcessData<T>(string Group, int Id)
{
string ConnectionString = "SomeConnectionStringName";
string sql = "select top 1 * from " + (typeof (T).Name) + " where " + Group + "Id = " + Id + ";";
DbContext d = new DbContext(ConnectionString);
var data = d.Database.SqlQuery<T> (sql).First();
//Do some stuff with the data...
html = "some tekst...";
foreach (var sourceProperty in data.GetType().GetProperties())
{
html = html.Replace("{#" + sourceProperty.Name + "#}", sourceProperty.GetValue(data, new object[] { }) == null ? "" : sourceProperty.GetValue(data, new object[] { }).ToString());
//enter code here
}
}
You most probably need to call ProcessData<T>(string Group, int Id) with some base type of VM_MailData. I assume that VM stands for "view model" and you have something like
public class MailData
{
}
public class VM_MailData : MailData
{
}
Where MailData class is actually the one that has a corresponding table.
So instead of calling ProcessData<VM_MailData >("some group", 1) you need to call ProcessData<MailData>("some group", 1).
P.S. You really should use parameterized queries to avoid SQL Injection!
I can see where you're heading :) so...
You have to create a map (dictionary) that maps from Type to appropriate table name. You can built that using some kind of convention based on the name of the type or the tables.
Use those to get available tables and views in the dabatase
SELECT SCHEMA_NAME(schema_id) as SchemaName, name as Name FROM sys.tables
SELECT SCHEMA_NAME(schema_id) as SchemaName, name as Name FROM sys.views
You can use the following script to get the primary key column of the table.
DECLARE #origin_table_name AS VARCHAR(50)
SET #origin_table_name = 'Your_table_name_goes_here'
SELECT
s.name AS TABLE_SCHEMA
, t.name AS TABLE_NAME
, c.name AS COLUMN_NAME
, k.name AS CONSTRAINT_NAME
, ic.key_ordinal AS ORDINAL_POSITION
FROM
sys.key_constraints AS k
JOIN sys.tables AS t ON t.object_id = k.parent_object_id
JOIN sys.schemas AS s ON s.schema_id = t.schema_id
JOIN sys.index_columns AS ic ON ic.object_id = t.object_id
AND ic.index_id = k.unique_index_id
JOIN sys.columns AS c ON c.object_id = t.object_id
AND c.column_id = ic.column_id
WHERE
k.type = 'PK'
AND t.name = #origin_table_name
Good luck

Asp.Net How can I pass parameters using an 'IN' clause in the query to refine a search

I'm following Mikes post on the IN Clause on http://www.mikesdotnetting.com/article/156/webmatrix-database-helpers-for-in-clauses but I'm having trouble adding additional params. As per his post, I started with some checkboxes for the categories and worked fine but I added some other checkboxes for the brands but it's not working. I'm not sure how to pass additional params to the in clause.
The idea of what I want to accomplish is to have a side bar with different product filters (categories, brands, age, price, etc) and as the user clicks it will update the results. Can someone please help me on this one?
This is the code i'm working with but this gives errors:
// for the categories
var cTemp = Request["categoryId"].Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
var cParms = cTemp.Select((s, i) => "#" + i.ToString()).ToArray();
var cIn = string.Join(",", cParms);
// for the brands
var bTemp = Request["brandId"].Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
var bParms = bTemp.Select((s, i) => "#" + i.ToString()).ToArray();
var bIn = string.Join(",", bParms);
var sql = "SELECT DISTINCT P.ProductID, J.CategoryID, J.BrandID, P.ProductName, P.Price, " +
"FROM Products P " +
"JOIN Junction J ON J.ProductID = P.ProductID " +
"WHERE J.CategoryID IN ({0}) OR J.BrandID IN ({1})";
var products = db.Query(String.Format(sql, cIn, bIn), cTemp, bTemp);
Inspect the value of String.Format(sql, cIn, bIn) - make it a separate string variable. You will see that you have duplicate parameter names in this SQL expression: #0, #1, etc.
When calling db.Query, do:
db.Query(<final sql statement>, allTemp)
where allTemp is concatenation of cIn and bIn.
Item 2 is the cause of the error that you see.
For the error you mentioned in the comment, try removing parameters from db.Query method.you are passing string array to sql parameters,which is not correct. Your method call should be this.
var products = db.Query(String.Format(sql, cIn, bIn));
I think there is also error in your WHERE clause handling. Try something like this..
var sql = "SELECT DISTINCT P.ProductID, J.CategoryID, J.BrandID, P.ProductName, P.Price, " +
"FROM Products P " +
"JOIN Junction J ON J.ProductID = P.ProductID ";
var whereClause = ""
if(!string.IsNullOrEmpty(cIn)||!string.IsNullOrEmpty(bIn))
{
whereClause = "WHERE";
if(!string.IsNullOrEmpty(cIn))
{
whereClause+=" J.CategoryID IN ({0}) ";
if(!string.IsNullOrEmpty(bIn))
whereClause+=" OR ";
}
if(!string.IsNullOrEmpty(bIn))
{
whereClause+=" J.BrandID IN ({1}) ";
}
}
sql = sql+whereClause;

Join data from multiple tables into SelectList, and precede each dataset with a caption in MVC

So this is a bit more complex than what I've been trying to do in the past. Essentially I have a few different tables: employee.employees, companies.employees, dbo.all_employees, and companies. They are represented by the following models, in order: employees1, employees, all_employees, and companies.
all_employees has 3 columns all_id, employee_id, and employee_type. I'm attempting to make a SelectList to populate a drop drop list, that will house all of the employees divided by their appropriate company. I've managed to get all the employees by name into the combo box, but I can't seem to figure out how separate the employees.
So think of it like this. If all_employees has a record with an employee_type of 1, they belong to our company, and their first and last name should be pulled from employees1, if they have anything other than an employee_type of 1 then they belong to another company, and should be pulled from employees
Here is my rough code that currently pulls all the employees from both tables, unions them, and places them into a select list. I simply need to figure out how to easily split them up so it looks something like
-- Select Employee --
-- Company 1
First Last
First Last
-- Company 2
First Last
-- Company 3
First Last
Code
var query1 = from c in _db.employees1
join p in _db.all_employees on c.employee_id equals p.employee_id into ps
select new { employee_id = c.employee_id, name = c.first_name + " " + c.last_name };
var query2 = from c in _db.employees
join p in _db.all_employees on c.employee_id equals p.employee_id into ps
select new { employee_id = c.employee_id, name = c.first_name + " " + c.last_name };
var merged = query2.Union(query1);
ViewBag.employeeid = new SelectList(merged, "employee_id", "name");
I have come across a possible solution in the form of a third party extension. It implements optgroup, and allows me to to easily control everything. I think this is the best solution but I'm not entirely sure.
The library is here.
And my modified code now looks similar to this:
Controller:
var query1 = from c in _db.employees1
join p in _db.all_employees on c.employee_id equals p.employee_id into ps
select new { employee_id = c.employee_id, name = c.first_name + " " + c.last_name, companyID = 1, company = "LightHouse Electric" };
var query2 = from c in _db.employees
join p in _db.all_employees on c.employee_id equals p.employee_id into ps
select new { employee_id = c.employee_id, name = c.first_name + " " + c.last_name, companyID = c.company_id, company = "Other" };
var merged = query2.Union(query1);
var data = merged.ToList().Select(t => new GroupedSelectListItem {
GroupKey = t.companyID.ToString(),
GroupName = t.company,
Text = t.name,
Value = t.employee_id.ToString()
});
ViewBag.employeeid = data;
View:
#Html.DropDownGroupListFor(model => Model.employee_id, (IEnumerable<GroupedSelectListItem>)ViewBag.employeeid,
"-- Select --", new {#data_val = "true", #data_val_required = "The Name field is required.", #class="form-control"})

Need to join two strings if both contain values, or return one value if first is NULL

enter code hereIn my SQL Server database I have my address information for the subNumber (e.g. Unit 802) and the streetNumber (e.g. 242 Elizabeth Street) stored separately.
I need to display these as one (i.e. 802/242 Elizabeth Street) if the subNumber contains a value, otherwise just return the streetNumber if it does not.
I've been working toward a solution using IF ELSE and a foreach loop after accessing the data through LINQ - but I'm stuck after the point where I have completed the loop. I would also be happy to do this with a SELECT Stored Procedure in SQL - open to suggestions!
DataClassesDataContext dc = new DataClassesDataContext();
var recent = from p in dc.Properties
orderby p.modtime descending
where p.status == "Current"
select new
{
rsub = (p.subNumber).ToString(),
rnumber = (p.streetNumber).ToString(),
rstreet = p.street,
rsuburb = p.suburb,
rurl = p.propertyURL,
};
foreach (var home in recent)
{
if (string.IsNullOrEmpty(home.rsub))
{
string rnum = home.rnumber;
}
else
{
string rnum = home.rsub + "/" + home.rnumber;
}
}
recentrepeater.DataSource = recent;
recentrepeater.DataBind();
Yahia gave the best option in c# - this is the SQL solution I have finally ended up with:
ALTER PROCEDURE GetPropertyShort
AS
SELECT TOP 5 ISNULL(convert(varchar(5), subNumber) + '/' + convert(varchar(5), streetNumber), convert(varchar(5), streetNumber)) as Number, street, suburb, propertyURL, modtime
FROM Property
ORDER BY modtime DESC
try
var recent = from p in dc.Properties
orderby p.modtime descending
where p.status == "Current"
select new
{
rsub = (p.subNumber).ToString(),
rnumber = (p.streetNumber).ToString(),
rnum = string.IsNullOrEmpty((p.subNumber).ToString()) ? (p.streetNumber).ToString() : (p.subNumber).ToString() + "/" + (p.streetNumber).ToString(),
rstreet = p.street,
rsuburb = p.suburb,
rurl = p.propertyURL,
};
Just a ternary conditional aka ?: operator in the "select" should do:
select new
{
house = p.subNumber != null
? p.subNumber + "/" + p.streetNumber
: p.streetNumber;
...
};
This makes the assumption street number is always there (or it might result in "xxx/" or null). It also assumes that sub is null (not just empty) if truly not present.
If it starts to get "too complicated", consider the following (which has slightly different rules than above, those are left to be figured out):
select new
{
house = PrettyHouseNumber(p.subNumber, p.streetNumber),
...
};
string PrettyHouseNumber(string sub, string street) {
// ?: could also be used here as well, but since invoking the method
// can be used as an expression itself, breaking it up like this also
// allows the use of other constructs
if (!string.IsNullOrEmpty(sub)) {
return sub + "/" + street;
} else {
return "" + street; // NULL will go to "", if it can even ever come up
}
}
Which should show how any expression, including a method call, can be used there -- pass it some data and get some data back :) While there are limits with expression trees and which ones can be efficiently turned into SQL, since this is just processing data already returned then there is nothing to worry about here.
Happy coding.
On the table level you could create a computed column; these are not stored - the value is 'created' when the column is queried.
CREATE TABLE [Customer]
(
[subNumber] NVARCHAR(256),
[streetNumber] NVARCHAR(256),
[fullAddress] AS (CASE
WHEN [subNumber] IS NULL THEN [streetNumber]
ELSE [subNumber] + N' ' + [streetNumber]
END)
);
GO
Or you can add it the table:
ALTER TABLE [Customer]
ADD COLUMN [fullAddress]
AS (CASE
WHEN [subNumber] IS NULL THEN streetNumber
ELSE [subNumber] + N' ' + streetNumber
END);
GO
Now the value will be directly-accessible from your EF model.

Categories

Resources