ASP.NET LINQ SQL get specific fields - c#

I am trying o set textboxes on an ASP.NET webpage using LINQ - SQL. Here is the code I have to perform the select statement:
EQCN = Request.QueryString["EQCN"];
var equipment = from n in db.equipments
where n.EQCN.ToString() == EQCN
select n;
How do I set TextBox1.text to be a specific field in the table?
Thanks so much
EDIT
I need to output every field in the table into different textboxes. So performing a query for ever single one seems a little much. There has to be a way to do this?
Thanks

Well you can select the appropriate field to start with:
EQCN = Request.QueryString["EQCN"];
var values = from n in db.equipments
where n.EQCN.ToString() == EQCN
select n.FieldYouWant;
// Or possibly Single, or First...
var singleValue = values.FirstOrDefault();
I think that's what you were after, but if it's not, please clarify your question.
EDIT: To answer your follow-up, you can use:
EQCN = Request.QueryString["EQCN"];
var query = from n in db.equipments
where n.EQCN.ToString() == EQCN
select n;
// Or possibly Single, or First...
var entity = query.Single();
textBox1.Text = entity.Name;
textBox2.Text = entity.Description;
textBox3.Text = entity.Title;
// etc
That's assuming you want to have access to everything in the entity. If the entity is very large and you only need a few fields, you might want to do something like this:
EQCN = Request.QueryString["EQCN"];
var query = from n in db.equipments
where n.EQCN.ToString() == EQCN
select new { n.Name, n.Description, n.Title };
// Or possibly Single, or First...
var projection = query.Single();
textBox1.Text = projection.Name;
textBox2.Text = projection.Description;
textBox3.Text = projection.Title;
I'm not sure I'd actually couple the data access and UI layers so closely, but that's a different matter...

You only need to perform the query once, but once that's done, you'll have to assign each field to a TextBox. Start by retrieving only the single item you want:
EQCN = Request.QueryString["EQCN"];
var equipment = (from n in db.equipments
where n.EQCN.ToString() == EQCN
select n).FirstOrDefault();
Then go through and assign each TextBox to the appropriate field:
txtName.Text = equipment.Name;
txtDescription.Text = equipment.Description;
txtValue1.Text = equipment.Value1;
txtValue2.Text = equipment.Value2;
//...
If you have several dozen TextBoxes to assign, you could set up a custom control that can be databound to an equipment object, but even then, you'll still have to write the binding code for your control.
The only way I can think of to totally automate this process is to name each TextBox after a field in your object, then use reflection to match them to values:
var textboxes = Panel1.Controls.OfType<TextBox>();
foreach (TextBox txt in textboxes)
{
string fieldname = txt.ID.Remove(0, 3); //"txtDescription" becomes "Description"
string value = equipment.GetType().GetProperty(fieldname).GetValue(equipment, null) as string;
txt.Text = value;
}

Related

Dynamic linq backslash in where clause

I use System.Linq.Dynamic to query entities with dynamic 'where' expressions. I'm querying object that has property "newValue" of string type. Exemplary value would be : "{\"ProcessId\":764, \"ProcessLength\":1000}".
I can't use == because I want to find all hits where the property contains "ProcessId:764", regardless on the rest of the string. The thing is, that stored string contains escape sign "\" and double quotes and I can't figure out what it should like exactly..
dbContext.Processes.Where("#newValue.Contains(\"ProcessId\":764\")") brings error, however dbContext.Processes.Where("#newValue.Contains(\":764\")") works correctly. I guess it must be something with backslashes or double quotes in my query but can't figure it out on my own..
There are two things to note here:
If you know at compile time the column that should be queried (i.e., newValue), just use standard Linq: var list = items.Where(i => i.NewValue.Contains("904")).ToList().
If you do want to use dyanmic Linq, What you'd usually want is to apply Where on some column, e.g. Where("SomeColumn.Contains("something")"), or Where("SomeColumn.Contains(#0)", new string[] {"something"}).
So, in your case, this should work: items.Where("newValue.Contains(\"904\")").
Doing Where("#newValue.Contains("something")") doesn't really make sense, since #newValue would be parsed as a string literal. See also this comment on a similiar question.
Here' a quick example:
public static void Main(string[] args)
{
var items = new []
{
new { Id = "1", Title = "ProcessId: 123"},
new { Id = "4", Title = "ProcessId: 456"},
new { Id = "7", Title = "ProcessId: 789"},
}.ToList();
// returns null, because the string "Title" doesn't contain the string "7"
var res1 = items.Where("#0.Contains(\"7\")", new string[] {"Title"}).FirstOrDefault();
// works - returns the 3rd element of the array
var res2a = items.Where("Title.Contains(#0)", new string[] {"ProcessId: 789"}).FirstOrDefault();
var res2b = items.Where("Title.Contains(\"ProcessId: 789\")").FirstOrDefault();
}
#HeyJude Thanks for the effort, but I still can't get it to work. It has somehow gone wronger and now I can't even fetch correct rows giving only ProcessId number..
Let me give you more detailed description of my setup. In the database there's a table with column "NewValue", I use this column to store json string of current (for the time of creating row in the table) representation of some object e.g. object Process. So the column stores for example string of {"ProcessId":904,"ProcessLength":1000}. To fetch this data from db I create collection of table's records: var items = (from l in db.JDE_Logs
join u in db.JDE_Users on l.UserId equals u.UserId
join t in db.JDE_Tenants on l.TenantId equals t.TenantId
where l.TenantId == tenants.FirstOrDefault().TenantId && l.Timestamp >= dFrom && l.Timestamp <= dTo
orderby l.Timestamp descending
select new //ExtLog
{
LogId = l.LogId,
TimeStamp = l.Timestamp,
TenantId = t.TenantId,
TenantName = t.TenantName,
UserId = l.UserId,
UserName = u.Name + " " + u.Surname,
Description = l.Description,
OldValue = l.OldValue,
NewValue = l.NewValue
});. Then I query it to find matching rows for given ProcessId number e.g. query = "#NewValue.Contains(\"904,)\")";
items = items.Where(query);
This should fetch back all records where NewValue column contains the query string, but this doesn't work. It compiles and 'works' but no data are fetched or fetched are only those records where 904 appears later in the string. Sounds stupid but this is what it is.
What should the query string look like to fetch all records containing "ProcessId":904?

Text box AutoCompleteSource (winForms) and LINQ query

I have a pre-populated text box with with an AutoCompleteCustomSource:
var source = new AutoCompleteStringCollection();
using(propertiesManagementDataContext db = new propertiesManagementDataContext())
{
var q =
(from t in db.GetTable<Tenant>()
select t.lname + " " + t.fname).ToArray();
source.AddRange(q);
}
txt_callerName.AutoCompleteCustomSource = source;
txt_callerName.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
txt_callerName.AutoCompleteSource = AutoCompleteSource.CustomSource;
It works fine, but I want to know the ID of the auto completed item. How to get it?
I tried like this, but had an error:
var q =
(from t in db.GetTable<Tenant>()
select new {lfname = t.lname + " " + t.fname, t.tenantID}).ToArray();
source.AddRange(q);
//this does not work, because q is not an array of strings anymore
How to autocomplete the textbox and save the connection between Lname, Fname and tenantID of the autocompleted items?
I don't see anything in the AutoCompleteStringCollection class that allows you store extra data for each string ... it's pretty much just a collection of strings.
This isn't ideal, but you could include the ID at the end of the string so it doesn't affect the auto-complete experience while the user is typing, then parse the value back out when they make a selection:
var q =
(from t in db.GetTable<Tenant>()
select string.Format("{0} {1} ({2})", t.lname, t.fname, t.tenantID)).ToArray();
Alternatively, you could use a ComboBox control, which (when configured properly) does everything your TextBox is doing, as well as supports setting the data source to a collection of any class you want (not limited to a collection of strings).
You would then specify the property visible to the user (name) with DisplayMember and then the value of each item (ID) with ValueMember.
You could store all the additional data in parallel Dictionary (or other similar collection)
var q =
(from t in db.GetTable<Tenant>()
select new {lfname = t.lname + " " + t.fname, t.tenantID});
Dictionary<String, Int32> idDictionary = new Dictionary<String, Int32>();
foreach(var item in q)
{
idDictionary.Add(item.lfname, item.tenantID);
source.AddRange(q);
}
...
String currentSuggestion = ...
Int32 id = idDictionary[currentSuggestion];
dbContext.Entities.RemoveById(id);
That is not the ideal solution, because you will have to somehow associate for each textBox with AutoCompletion its own dictionary(either storing it in parallel, or subclassing the TextBox). Also there is possibility that lfname can occur twice in the query.

Lambda SQL Query / Manipulate String At Query Or After Result

I'm using C#, EF5, and Lambda style queries against SQL.
I have the usual scenario of binding data to gridviews. Some of the results for my columns may be too long (character count) and so I only want to display the first 'n' characters. Let's say 10 characters for this example. When I truncate a result, I'd like to indicate this by appending "...". So, let's say the following last names are returned:
Mercer, Smith, Garcia-Jones
I'd like them to be returned like this:
Mercer, Smith, Garcia-Jon...
I was doing something like this:
using (var context = new iaiEntityConnection())
{
var query = context.applications.Where(c => c.id == applicationPrimaryKey);
var results = query.ToList();
foreach (var row in results)
{
if (row.employerName.Length > 10)
{
row.employerName = row.employerName.Substring(0, Math.Min(10, row.employerName.ToString().Length)) + "...";
}
if (row.jobTitle.Length > 10)
{
row.jobTitle = row.jobTitle.Substring(0, Math.Min(10, row.jobTitle.ToString().Length)) + "...";
}
}
gdvWorkHistory.DataSource = results;
gdvWorkHistory.DataBind();
However, if I change my query to select specific columns like this:
var query2 = context.applications.Select(c => new
{
c.id,
c.applicationCode,
c.applicationCategoryLong,
c.applicationType,
c.renew_certification.PGI_nameLast,
c.renew_certification.PGI_nameFirst,
c.renew_certification.PAI_homeCity,
c.renew_certification.PAI_homeState,
c.reviewStatusUser,
c.dateTimeSubmittedByUser
})
The result appears to become read-only if specific columns are selected, and I really should be selecting just the columns I need. I'm losing my ability to edit the result set.
So, I'm rethinking the entire approach. There must be away to select the first 'n' characters on select, right? Is there anyway to append the "..." if the length is > 10 on select? That seems trickier. Also, I guess I could parse through the gridview after bind and make this adjustment. Or, perhaps there is a way to maintain my ability to edit the result set when selecting specific columns?
I welcome your thoughts. Thanks!
To quote MSDN
Anonymous types provide a convenient way to encapsulate a set of read-only properties into a single object without having to explicitly define a type first.
So you would have to define a class and select into that if you want read write capability.
e.g.
public class MyClass {
public int id { get; set; }
public string applicationCode {get; set; }
// rest of property defintions.
}
var query2 = context.applications.Select(c => new MyClass {
id = c.id,
applicationCode = c.applicationCode,
// Rest of assignments
};
As to just providing 10 character limit with ... appended. I'm going to assume you mean on the applicationcategoryLog field but you can use the same logic on other fields.
var query2 = context.applications.Select(c => new
{
c.id,
c.applicationCode,
applicationCategoryLong = (c.applicationCategoryLong ?? string.Empty).Length <= 10 ?
c.applicationCategoryLong :
c.applicationCategoryLong.Substring(0,10) + "...",
c.applicationType,
c.renew_certification.PGI_nameLast,
c.renew_certification.PGI_nameFirst,
c.renew_certification.PAI_homeCity,
c.renew_certification.PAI_homeState,
c.reviewStatusUser,
c.dateTimeSubmittedByUser
})

Multiple fields from LINQ to Text Box

how can I pass value from selected field (LINQ) to textbox in winforms?
If single fields, I just do like this
var result = from row in dtValueBranch.AsEnumerable()
where row.Field<int>("branchID") == idBranch
select row.Field<string>("branchName");
StringBuilder sb = new StringBuilder();
foreach (string s in result)
{
sb.Append(s + Environment.NewLine);
}
tbBranch.Text = sb.ToString();
So this is the code LINQ to many fields
var result = from row in dtValueBranch.AsEnumerable()
where row.Field<int>("branchID") == idBranch
select new
{
BranchName = row["branchName"].ToString(),
branchTel = row["branchTel1"].ToString(),
// And many more fields
};
How can I to implement each fields to each textbox?
Keeping in mind that your result query may have multiple rows, your question appears to be focused on how to access the fields of one row. You can do that like this:
var row = result.First(); // select first row of results
textbox1.Value = row.BranchName;
textbox2.Value = row.branchTel;
// etc..
The select new syntax in your query creates an anonymous type in the result enumeration. You can't refer to that type by name, but you can create local variables (like row) if you use the var declaration style and let the compiler do type inferencing.
If you want to cram all the values of one field across all rows into into one textbox (as in your first code sample), you can do something like this:
StringBuilder sbBranch = new StringBuilder();
StringBuilder sbBranchTel = new StringBuilder();
// etc
foreach (var row in result)
{
sbBranch.Append(row.BranchName);
sbBranch.Append(Environment.NewLine);
sbBranchTel.Append(row.branchTel);
sbBranchTel.Append(Environment.NewLine);
// etc
}
tbBranch.Text = sbBranch.ToString();
tbBranchTel.Text = sbBranchTel.ToString();
// etc
However, if you're wanting to display multiple rows of multiple fields of data, you might want to look at using a data grid control instead of a herd of textboxes. You'll save yourself a lot of effort, and your users will probably thank you too.
You can do like this:
var rows = dtValueBranch.AsEnumerable()
.Where(row => row.Field<int>("branchID") == idBranch);
textBox1.Value = string.Join(Environment.NewLine,
rows.Select(row => row.Field<string>("branchName"));
textBox2.Value = string.Join(Environment.NewLine,
rows.Select(row => row.Field<string>("branchTel1"));

Is there a way to access the columns in a Dapper FastExpando via string or index?

I am pulling in a Dapper FastExpando object and want to be able to reference the column names dynamically at run time rather than at design/compile time. So I want to be able to do the following:
var testdata = conn.Query("select * from Ride Where RiderNum = 21457");
I want to be able to do the following:
foreach( var row in testdata) {
var Value = row["PropertyA"];
}
I understand that I can do:
var Value = row.PropertyA;
but I can't do that since the name of the property i'm going to need won't be known until runtime.
The answer from this SO Question doesn't work. I still get the same Target Invocation exception. So...
Is there any way to do what I want to do with a Dapper FastExpando?
Sure, it is actually way easier than that:
var sql = "select 1 A, 'two' B";
var row = (IDictionary<string, object>)connection.Query(sql).First();
row["A"].IsEqualTo(1);
row["B"].IsEqualTo("two");
Regarding the portion of the title "or index?" - I needed to access results by index since the column names being returned changed sometimes, so you can use a variation of Sam Saffron's answer like this:
var sql = "select 1, 'two'";
var row = (IDictionary<string, object>)connection.Query(sql).First();
row.Values.ElementAt(0).IsEqualTo(1);
row.Values.ElementAt(1).IsEqualTo("two");
There a simple way to access fields direct below sample
string strConexao = WebConfigurationManager.ConnectionStrings["connection"].ConnectionString;
conexaoBD = new SqlConnection(strConexao);
conexaoBD.Open();
var result = conexaoBD.Query("Select Field1,Field2 from Table").First();
//access field value result.Field1
//access field value result.Field2
if (result.Field1 == "abc"){ dosomething}

Categories

Resources