How to get text from LINQ2SQL query? - c#

I have a web page in which I am giving USER the options of writing notes. Now when ever the web page checks that a USER is:abc then it pulls up the note from the MEMO Table.
Here is my code in Page_Load():
using (EntityMemoDataContext em = new EntityMemoDataContext())
{
int getEntity = Int16.Parse(Session["EntityIdSelected"].ToString());
var showMemo = from r in em.EntityMemoVs_1s
where r.EntityID == getEntity
select r.Memo;
tbShowNote.Text = String.Join(#"<br />", showMemo);
}
tbShowNote is showing me value like this:
test<br />test1<br />test1<br />test4<br />test4
And I want it like this:
Test
Test1
Test2 ...
tbShowNote is a TextBox!

You only asked for the first memo, so that's what you got back. If you want it enumerated with each one on it's own line in html, you could do this:
using (EntityMemoDataContext em = new EntityMemoDataContext())
{
int getEntity1 = Int16.Parse(Session["EntityIdSelected"].ToString());
var showMemo = from r in em.EntityMemoVs_1s
where r.EntityID == getEntity1
select new
{
r.Memo
};
tbShowNote.Text = String.Join(#"<br />", showMemo);
}
The key takeaway is if r.Memo is of type string, then the LINQ query you executed gave you back a IQueryable<string>. It's on you to decide if you want to flatten that list later.
Edit: Equiso made a good observation in that you're actually returning an IQueryable of an anonymous type, not IQueryable<string> due to the new { ... } syntax. I'd say combine his answer with mine and run with it:
var showMemo = from r in em.EntityMemoVs_1s
where r.EntityID == getEntity1
select r.Memo;
tbShowNote.Text = String.Join(#"<br />", showMemo);

The problem is in the select part of your linq query, you are wrapping your results in an anonymous type, that is why when you call ToString() you see { Memo = test }. You probably want it like this:
var showMemo = from r in em.EntityMemoVs_1s
where r.EntityID == getEntity1
select r.Memo;
After that showMemo will contain just strings.

It looks like your showMemo is a collection and you are then just assigning the top value? If you are putting them in one string then you need to aggregate them together.

Related

How to sort dynamically in mongodb

I have a "sort" query parameter. This maybe looking like this:
?sort=-name,+number
Now I want to read this and build a sort query for the c# MongoDB-Driver.
I thought of something like this:
var sortByList = parameters.Sort?.Split(',');
foreach (var sortBy in sortByList)
{
if (sortBy.StartsWith('-'))
// add to sort query decending ?!?
else
// add to sort query ascending ?!?
}
The only way I found so far is to build a string like "{name:-1, number:1}" and give this to the .Sort-method. But so I have build to build many strings that I really don't need.
Isn't there a way to do something like:
var sortDefinition = new SortDefintion();
var sortByList = parameters.Sort?.Split(',');
foreach (var sortBy in sortByList)
{
if (sortBy.StartsWith('-'))
sortDefinition.Add(sortBy.Substring(1), -1);
else
sortDefinition.Add(sortBy.Substring(1), 1);
}
return db.GetCollection<BsonDocument>("sortTest").Sort(sortDefintion).ToList();
You can solve it like this:
var bldr = Builders<BsonDocument>.Sort;
var sortDefinitions = sortByList.Select(x =>
{
SortDefinition<BsonDocument> sortDef;
var propName = x.Substring(1);
if (x.StartsWith("-"))
sortDef = bldr.Descending(propName);
else
sortDef = bldr.Ascending(propName);
return sortDef;
});
var sortDef = bldr.Combine(sortDefinitions);
return db
.GetCollection<BsonDocument>("sortTest")
.Find(Builders<BsonDocument>.Filter.Empty)
.Sort(sortDef)
.ToList();
Above code uses a Linq Select to create a SortDefinition<BsonDocument> for each string in the list and combines these definitions into a single sort definition afterwards. This sort definition is then applied to the Find.

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?

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
})

Convert DataTable to LINQ: Unable to query multiple fields

Importing a spreadsheet I have filled a DataTable object with that data and returns expected results.
Attempting to put this into a format I can easily query to search for problem records I have done the following
public void Something(DataTable dt)
{
var data = from row in dt.AsEnumerable()
select row["Order"].ToString();
}
Works as expected giving me a list of orders. However I cannot add other fields to this EnumerableRowCollection. Attempting to add other fields as follows gives me an error
public void Something(DataTable dt)
{
// row["Version"] throws an error on me
var data = from row in dt.AsEnumerable()
select row["Order"].ToString(), row["Version"].ToString();
}
Error: "A local variable named 'row' cannot be declared in this scope because it would give a different meaning to 'row' which is already used in a 'child' scope to donate something else"
I'm thinking I need to alias the column name but I'm having no luck. What am I missing here?
It sounds like you're writing a bad select statement. Try the following:
public void Something(DataTable dt)
{
var data = from row in dt.AsEnumerable()
select new {
Order = row["Order"].ToString(),
Something = row["Something"].ToString(),
Customer = row["Customer"].ToString(),
Address = row["Address"].ToString()
};
}
That will create a new collection of Anonymously Typed objects that you can iterate over and use as needed. Keep in mind, though, that you want be able to return data from the function. If you need that functionality, you need to create a concrete type to use (in place of anonymous types).
I think you should use select new like this query for example:
var q = from o in db.Orders
where o.Products.ProductName.StartsWith("Asset") &&
o.PaymentApproved == true
select new { name = o.Contacts.FirstName + " " +
o.Contacts.LastName,
product = o.Products.ProductName,
version = o.Products.Version +
(o.Products.SubVersion * 0.1)
};
You probably want the following.
var data = from row
in dt.AsEnumerable()
select new { Order = row["Order"].ToString(), Version = row["Version"].ToString() };

Specifying return rows in LINQ2DataSet

I have a requirement to extract a distinct subset of rows from a DataTable, and thought LINQ2DataSets may be a useful and clean way to do this, however it appears that it is not possible to simply identify return rows from a LINQ2DS query as follows
var result = from r in fips.AsEnumerable() select
r.Field<string>("FACILITY_PROCESS_SUB_GROUP_CODE"),
r.Field<string>("PROCESS_SUB_GROUP_NAME"),
r.Field<string>("...
as I start getting errors after the first comma.
Is this a correct assumption, and how would I get around it to return a subset of columns from the dataset that I can apply a Distinct() method to?
You forgot the new statement and field names:
var result = from r
in fips.AsEnumerable()
select new
{
FacProcess = r.Field<string>("FACILITY_PROCESS_SUB_GROUP_CODE"),
GroupName = r.Field<string>("PROCESS_SUB_GROUP_NAME"),
Item3 = r.Field<string>("Item3")
};
You can also explicitly declare that you are going to use a type:
var result = from r
in fips.AsEnumerable()
select new MyType("InitClassParams")
{
FacProcess = r.Field<string>("FACILITY_PROCESS_SUB_GROUP_CODE"),
GroupName = r.Field<string>("PROCESS_SUB_GROUP_NAME"),
Item3 = r.Field<string>("Item3")
};
Scott Guthrie (VP Developer Devision, Microsoft) has some good info about LINQ (he talks about LINQ to SQL, but most of it applies regardless).
Then apply the distinct clause:
var result = from r
in fips.AsEnumerable()
select new
{
FacProcess = r.Field<string>("FACILITY_PROCESS_SUB_GROUP_CODE"),
GroupName = r.Field<string>("PROCESS_SUB_GROUP_NAME"),
Item3 = r.Field<string>("Item3")
}
distinct;
Then put it to a list or iterate over it. Nothing will be selected/distincted/etc until something like on of the following is run:
var list = result.ToList()
foreach(var item in result) {}

Categories

Resources