I would like to know is if I have an excel file and I am trying to get data via linq query will this be posible?
Excel file format
+-----------------+-------------+
| Inputlocation | Inputvalue |
+-----------------+-------------+
| 1 | Hello |
+-----------------+-------------+
| 2 | World!!! |
+-----------------+-------------+
Now If I am using Linq query given below is it possible to get Inputvalue data
var fileName = #"C:\Users\jshah\Documents\Visual Studio 2013\Projects\QA_ExpScript\QA_ExpScript\Excel\Inputdata.xls";
string sheetName = "Input";
var book = new LinqToExcel.ExcelQueryFactory(fileName);
var users = from x in book.Worksheet(Input) select x;
foreach (var x in users)
{
Console.WriteLine(x["1"]);
}
I am trying to do here is where inputlocation is "1" give me Inputvalue which is "Hello". Am I on a correct way to specify the query?. Also I am using this again and again later in my code. So please give better solution for this.
You can use where clause to filter the data like this:-
var users = from x in book.Worksheet()
where x["Inputlocation"].Cast<int>() == 1
select x["Inputvalue"].Cast<string>();
Then you can simply iterate through users:-
foreach (var item in users)
{
Console.WriteLine(item.Inputvalue); //This will print "Hello"
}
Although IMHO its always better to create a matching type to avoid any exceptions that can occur by typos when specifying the column names.
public class User
{
public int Inputlocation { get; set; }
public string Inputvalue { get; set; }
}
and here is the query:-
var users = from x in book.Worksheet<User>()
where x.Inputlocation == 1
select x;
This is kinda same as I am doing but somewhat answering the question. But don't what which #RahulSingh is saying.
Also related to #Chris 1 in the code. And creator of this post is i think saying that he does not want to change anythhing in his function. The only change he wants is Console.WriteLine(x["1"]); or Console.WriteLine(x["2"]); to get Inputvalue
Reference to my post
Related
I am using the FitNesse / FitSharp (c#) for testing purposes.
I can create normal fixture like ColumnFixtures, RowFixtures, DoFixtures etc. but not I am looking for a way to read columns and bind them dynamically.
The reason for this is, I still already have a huge amount of Pojo objects in my own library and don't want to repeat all class members again. Therefor i am searching for a way to handle column dynamically.
e.g.
!|Create| pojoType | record | pojoName |
|Name | LastName | Address| Misc |
| a | b | c | d |
public class DynamicHandling : DoFixture () {
public void CreateRecord(string type, string name) {
var clazz = GetClazzOfType();
var headers = GetHeadersOfColumn();
var values = GetValuesOfColumn();
var pojo = DoBindingAndAssignValues(headers, rows, clazz);
// ... Continue with whatever e.g. ...
var name = pojo.Name;
var lastName = pojo.LastName;
var address = pojo.Address;
address.split(';') ...
}
}
Any idea ?
Take a look at the source code for the Compute fixture (https://fitsharp.github.io/Fit/ComputeFixture.html) and see if it helps.
You can write a fixture that processes cells dynamically like this:
public class MyFixture: Interpreter {
public void Interpret(CellProcessor processor, Tree<Cell> table) {
new Traverse<Cell>()
.Rows.Header(row => FunctionThatDoesSomethingWithTheHeaderRow(row))
.Rows.Rest(row => FunctionThatDoesSomethingWithEachSubsequentRow(row))
.VisitTable(table);
}
...
}
There's other sets of rows you can traverse - check out the Traverse source code.
So I have a simple key-value table BillTypes in my SQL Server. It looks like this:
+----+-------------+
| Id | Description |
+----+-------------+
| 1 | OK |
| 2 | Missing |
| 3 | Maximum |
| 4 | Minimum |
| 5 | Error |
+----+-------------+
The table holds different types of bill states. I have another table Items with a foreign key BillType, referring to Id in the previous table.
+----------+------+--------+
| IdItem | Cash |BillType|
+----------+------+--------+
| * | * | * |
| * | * | * |
| * | * | * |
| ... |... | ... |
+----------+------+--------+
Then, in my application I get data from the second table via a stored procedure. In this sp, I am not sure if should select the BillType as it is, a tinyint, or use an innerjoin to return the description instead. The thing is, my application has some logic depending on the BillType, i.e. rows will be processed differently depending on the BillType. Should my logic depend on the Id or the description??
In code, should I have something like this?
DataTable dt = ...//call stored procedure that selects the BillType id
foreach(Datarow r in dt)
{
if(r["BillType"] == 3) ... //use logic
}
or this?
DataTable dt = ...//call stored procedure that selects the BillType description
foreach(Datarow r in dt)
{
if(r["BillType"] == "Maximum") ... //use logic
}
I am currently using the second way, with descriptions, because I think it makes code more readable. I am however worried about the possibility that someone might change the descriptions and break my application logic. On the other hand, using ids would be less readable(though i could work around this with an enum) and would be invulnerable to description changes, but still if someone changed an id, things would break.
To be honest, we don't expec anyone to mess around with the first table, since we made it specially for this application. Still, I am new to SQL and I am trying to learn the best practices of application-SQL interaction, so I would like to know how experienced people do it
Please consider this a comment rather than an answer (I don't yet have enough rep to comment).
I prefer the latter (as you are doing), where I rely on the description.
If your IDs are SQL indentity fields (which auto-increment) Consider the following scenario:
You build your app and database in DEV environment
The production deployment gets back out and re-run
Now, rather than IDs 1,2,3 you have 4,5,6
Generally speaking, it makes more sense to rely on IDs instead of values. After all, IDs should be unique, whereas values can have duplicates/change. Although you are not expecting any changes to the BillTypes table, I wouldn't use the string values, as you suggested.
Since updates/deletes/inserts can still happen in the BillTypes table and you want to be prepared as well as have readable code, the easiest thing to do would be if you define your own enum as such:
public Enum BillTypesEnum
{
OK = 1,
Missing = 2,
Maximum = 3,
Minimum = 4,
Error = 5
};
If something happens and you need to add something to the database, you do it and then change the Enum. It would also work if you delete the "Error" entry and insert "Average". You would not get Average=5 but probably Average=6 or something higher. The enum structure lets you define the values with no problem.
Then you can use it all over your code, not just in this single instance. Your code is modified below:
DataTable dt = ...//call stored procedure that selects the BillType id
foreach(Datarow r in dt)
{
if(r["BillType"] == (int)BillTypesEnum.Maximum) ... //use logic
}
This makes the code more readable then before, you dont have to hard-code the values all over your code but just in one place. And if it happens,that you will not be changing the database, then it's just a plus.
Another option would be to do the spGetAllBillTypes (select * from tblBillTypes) and then internally create a dictionary.
Dictionary<string,int> dictBillTypes = new Dictionary<string,int>();
int = billTypeId
string = billTypeText
When you retrieve your data from the child table (the one with the foreign key), you retrieve your billtypetext.
You can then do it like this:
DataTable dt = ...//call stored procedure that selects the BillType id
foreach(Datarow r in dt)
{
if(r["BillType"] == dictBillTypes["Maximum"]) ... //use logic
}
...but this is still an incomplete solution, because here, you rely on two things:
1. that the billTypeText will not change (if it does, you have to change it in the code)
2. that the billTypeText will not have duplicates (otherwise you will get an exception about duplicate key value in the dictionary)
Another option is to turn it around:
Dictionary<int,string> dict = new Dictionary<int,string>();
and do the search based on the value instead of the key. But that makes the code less readable and you dont really gain a lot from this.
If you are worried about the ID changing, I would recommend creating an Abstract Class to hold the ID values. This can be referenced like an Enum, and it will look up the ID on the first call, and cache the result:
public abstract class BillType
{
private static readonly string c_ok = "ok";
private static readonly string c_missing = "missing";
private static readonly string c_maximum = "maximum";
private static readonly string c_minimum = "minumum";
private static readonly string c_error = "error";
private static int? _ok = null;
private static int? _missing = null;
private static int? _maximum = null;
private static int? _minimum = null;
private static int? _error = null;
public static int OK
{
get
{
if (_ok == null)
_ok = GetBillTypeID(c_ok);
return (int)_ok;
}
}
public static int Missing
{
get
{
if (_missing == null)
_missing = GetBillTypeID(c_missing);
return (int)_missing;
}
}
public static int Maximum
{
get
{
if (_maximum == null)
_maximum = GetBillTypeID(c_maximum);
return (int)_maximum;
}
}
public static int Minimum
{
get
{
if (_minimum == null)
_minimum = GetBillTypeID(c_minimum);
return (int)_minimum;
}
}
public static int Error
{
get
{
if (_error == null)
_error = GetBillTypeID(c_error);
return (int)_error;
}
}
private static int GetBillTypeID(string identifier)
{
using (SqlConnection conn = new SqlConnection("your connection string")
{
conn.Open();
using (SqlCommand cmd = new SqlCommand("spGetBillTypeId", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("Description", identifier);
return Convert.ToInt32(cmd.ExecuteScalar());
}
}
}
}
I would also have a Stored Procedure on your database to do a lookup for that ID:
Create Procedure spGetBillTypeId (#Description Varchar (20))
As Begin
Select Id
From BillTypes
Where Description = #Description
End
With this, you can simply call BillType.Missing and it will pull the Id of missing, cache it, and return 2.
(Note, most of this was copy/paste, so mind random errors I didn't catch).
If you don't expect the values to change, however, and you are okay with making code changes if that does happen, you can simply make an Enum:
public enum BillType
{
OK = 1,
Missing = 2,
Maximum = 3,
Minimum = 4,
Error = 5
}
I am working on a search form in C# and I have two tables which users can search in them, one of them is property table and another one is users. As you know each user can have more than one property. So if I want to find users that have a property with color=red and price X when I run query it gives me many users and some of them is duplicated I mean the the phone number of users are same. So as the result of a query that user does I have a result such as this
User.name|user.phone|product.color|product.price|product.id
-----------------------------------------------------------
a |9828393999|red |XX |yt3
a |9828393999|red |XX |y23
b |9828393994|red |XX |3t3
b |9828393994|red |XX |4t3
This is a result of query that user performs..How I can get only phone numbers and name? I want something like this
User.name|user.phone|product.color|product.price|product.id
-----------------------------------------------------------
a |9828393999|red |XX |y23
b |9828393994|red |XX |4t3
Here is a sample query that I get from user
select
u.Name, u.Family, u.OBJECTID, u.phone,
p.number, p.Energy, p.Area, p.contex, p.title
from
[dbo].[user] as u, [dbo].[PROPERTY] as p
where
u.OBJECTID = p.owner_ID and [contex] = 0 and [title] = 2
No matters product.id, I just want the phone numbers.. So what is best method to do it?
Can I perform such thing in SQL Server? Or I must use codes?
One way that I can do is loop among data and get phone numbers. But I think it is some how not a good method..Can you help me find a good solution for this?
Thank you very much
Here's what I do for this type of thing...
Step 1) Create a model of your class...
public class MyModel {
public string UserName {get;set;}
public string UserPhone {get;set;}
public string ProductColor {get;set;}
public string ProductPrice {get;set;}
public string ProductID {get;set;}
}
Then I use Enitity Framework to project the results into that model like this.
using(var db = new MyEntities(){
string Query = "Select XYZ from Tablea,TableB where something=#parm";
SqlParameter[] parms = {new SqlParameter{name = "parm" value="somevalue");
var stuff = db.Database.SQLQuery<MyModel>(query, parms.ToArray());
return stuff.ToList();
}
Stuff will contain IEnumerable
Now you can use LINQ to filter what ever you want.
var grp = stuff.GroupBy(p=>p.UserPhone);
var justPhoneNumbers = stuff.Where(p=>p.ProductColor=="Red").Select(p=>p.UserPhone).ToList();
var filtered = stuff.Where(p=>p.ProductColor=="Red").ToList();
var filtered2 = stuff.Where(p=>p.ProductColor=="Red");
filtered2= filtered2.Where(p=>p.UserName == "Jones");
var finallist = filtered2.ToList();
Then just bind the results to the view and you're all set.
I have a stored procedure that is returning data in this format:
HotelID | Price
---------------------
1 | 20
1 | 30
2 | 25
4 | 40
4 | 50
I'm getting the results like so:
ISingleResult<spResult> results = DataContext.sp();
I'd like to get a list of Hotels, based on the data returned from the stored procedure. Something like:
int[] uniqueHotelIds = GetUniqueHotelIdsFromResults(results);
List<Hotel> hotels = (from h in DataContext.Hotels
where uniqueHotelIds.Contains(h.HotelID)
select h).ToList();
I don't have much experience with ISingleResult, but could you do:
int[] uniqueHotelIds = results.Select(x => x.HotelID).Distinct();
You can also iterate through the SingleResult like this:
var myFancyResult;
ISingleResult<spResult> results = DataContext.sp();
foreach (var spResult in results)
{
myFancyResult = spResultin.NameOfColumn;
//Do something else with the data.
}
You can then name the result in the Stored Procedure like this, to give a clear picture:
SELECT ISNULL(#Result, 0) AS Result
ISNULL also ensures you don't have to deal with Nullables in C#.
In case anyone still needs the answer:
NOTE: ISingleResult, as the name implies, will return one result. In the code block below, it maps the resulting SP call to the "resultObject" class. The second line gives an example of the same code with parameters. You'd then want to check and make sure it's not null (depending on your SP).
ISingleResult<spResult> results = DataContext.sp();
var newObject = results.Select(r => new resultObject()).SingleOrDefault();
// or
var newObject = DataContext.sp().Select(r => new resultObject()).SingleOrDefault();
// with parameters
var newObject = DataContext.sp(id, count).Select(r => new resultObject(id, count)).SingleOrDefault();
I have a linq expression that I've been playing with in LINQPad and I would like to refactor the expression to replace all the tests for idx == -1 with a single test. The input data for this is the result of a free text search on a database used for caching Active Directory info. The search returns a list of display names and associated summary data from the matching database rows. I want to extract from that list the display name and the matching Active Directory entry. Sometimes the match will only occur on the display name so there may be no further context. In the example below, the string "Sausage" is intended to be the search term that returned the two items in the matches array. Clearly this wouldn't be the case for a real search because there is no match for Sausage in the second array item.
var matches = new []
{
new { displayName = "Sausage Roll", summary = "|Title: Network Coordinator|Location: Best Avoided|Department: Coordination|Email: Sausage.Roll#somewhere.com|" },
new { displayName = "Hamburger Pattie", summary = "|Title: Network Development Engineer|Location: |Department: Planning|Email: Hamburger.Pattie#somewhere.com|" },
};
var context = (from match in matches
let summary = match.summary
let idx = summary.IndexOf("Sausage")
let start = idx == -1 ? 0 : summary.LastIndexOf('|', idx) + 1
let stop = idx == -1 ? 0 : summary.IndexOf('|', idx)
let ctx = idx == -1 ? "" : string.Format("...{0}...", summary.Substring(start, stop - start))
select new { displayName = match.displayName, summary = ctx, })
.Dump();
I'm trying to create a list of names and some context for the search results if any exists. The output below is indicative of what Dump() displays and is the correct result:
displayName summary
---------------- ------------------------------------------
Sausage Roll ...Email: Sausage.Roll#somewhere.com...
Hamburger Pattie
Edit: Regex version is below, definitely tidier:
Regex reg = new Regex(#"\|((?:[^|]*)Sausage[^|]*)\|");
var context = (from match in matches
let m = reg.Match(match.summary)
let ctx = m.Success ? string.Format("...{0}...", m.Groups[1].Value) : ""
select new { displayName = match.displayName, context = ctx, })
.Dump();
(I know this doesn't answer your specific question), but here's my contribution anyway:
You haven't really described how your data comes in. As #Joe suggested, you could use a regex or split the fields as I've done below.
Either way I would suggested refactoring your code to allow unit testing.
Otherwise if your data is invalid / corrupt whatever, you will get a runtime error in your linq query.
[TestMethod]
public void TestMethod1()
{
var matches = new[]
{
new { displayName = "Sausage Roll", summary = "|Title: Network Coordinator|Location: Best Avoided|Department: Coordination|Email: Sausage.Roll#somewhere.com|" },
new { displayName = "Hamburger Pattie", summary = "|Title: Network Development Engineer|Location: |Department: Planning|Email: Hamburger.Pattie#somewhere.com|" },
};
IList<Person> persons = new List<Person>();
foreach (var m in matches)
{
string[] fields = m.summary.Split('|');
persons.Add(new Person { displayName = m.displayName, Title = fields[1], Location = fields[2], Department = fields[3] });
}
Assert.AreEqual(2, persons.Count());
}
public class Person
{
public string displayName { get; set; }
public string Title { get; set; }
public string Location { get; set; }
public string Department { get; set; }
/* etc. */
}
Or something like this:
Regex reg = new Regex(#"^|Email.*|$");
foreach (var match in matches)
{
System.Console.WriteLine(match.displayName + " ..." + reg.Match(match.summary) + "... ");
}
I haven't tested this, probably not even correct syntax but just to give you an idea of how you could do it with regex.
Update
Ok, i've seen your answer and it's good that you posted it because I think i didn't explain it clearly.
I expected your answer to look something like this at the end (tested using LINQPad now, and now i understand what you mean by using LINQPad because it actually does run a C# program not just linq commands, awesome!) Anyway this is what it should look like:
foreach (var match in matches)
Console.WriteLine(string.Format("{0,-20}...{1}...", match.displayName, Regex.Match(match.summary, #"Email:(.*)[|]").Groups[1]));
}
That's it, the whole thing, take linq out of it, completely!
I hope this clears it up, you do not need linq at all.
like this?
var context = (from match in matches
let summary = match.summary
let idx = summary.IndexOf("Sausage")
let test=idx == -1
let start =test ? 0 : summary.LastIndexOf('|', idx) + 1
let stop = test ? 0 : summary.IndexOf('|', idx)
let ctx = test ? "" : string.Format("...{0}...", summary.Substring(start, stop - start))
select new { displayName = match.displayName, summary = ctx, })
.Dump();