Using Parameters in LINQ - linq

net. I have a doubt. How do we introduce user defined variables as parameters in where clause of a LINQ query. I am querying an XML file. Here is my code
XElement books = XElement.Load(#"Friends.xml");
var titles =
from book in books.Elements("Friend")
where (string)book.Element("Date") == "27" && (string)book.Element("Month") == "05"
select book.Element("Name");
foreach (var title in titles)
Console.WriteLine(title.Value);
Instead of harcoding values 27 and 05, I want to use variables instead.How to use them?
Sorry for the dumb question, I misunderstood the problem. Actually I am blocking certain dates in a calendar. Now using the
private void calendar1_SelectedDatesChanged(object sender, SelectionChangedEventArgs e)
{....}
works only for non blocked dates. Since a particular day I tried with the variable was a blocked one, it wasn't working. Now please suggest me a solution for this. All I need is to click on a date(blocked or non blocked) and I have to run a event. Which event should I use??

use a simply variable:
XElement books = XElement.Load(#"Friends.xml");
string yourDate = "27";
string yourMonth = "05";
var titles =
from book in books.Elements("Friend")
where (string)book.Element("Date") == yourDate && (string)book.Element("Month") == yourMonth
select book.Element("Name");
foreach (var title in titles)
Console.WriteLine(title.Value);
And so on. Of course, use good names that are readable according your code and system

In addition, I think you could define a class of book with appropriate properties as XML tag. For example :
class Book {
string Date {...} //
}
It's could be quite easy when reading XML file. Moreover, it could be nice if you build your own tree data structures executing XML file.

Related

C# Remove object from list stored in an ASP session

I am making a small eBook Store as a project. I am storing the cart in the ASP session as a list of objects. Now, in the checkout page, I am showing that list of objects in a list box and allowing the user to delete an item if needed. This is my code
protected void btnCart_Click(object sender, EventArgs e)
{
List<Title> cartItems = (List<Title>)Session["eStoreCart"];
int itemToRemove = Int32.Parse(lbCartItems.SelectedItem.Value);
Title ttl = ebs.Titles.SingleOrDefault(t => t.TitleId == itemToRemove);
cartItems.Remove(ttl);
Session["eStoreCart"] = cartItems;
FillListBox();
}
Apparently, the number of items in cartItems are same before and after the Remove() method is called. Where am I going wrong?
A similar method was used in Add to Card with cartItems.Add(ttl), which is working flawlessly.
Instead of
Title ttl = ebs.Titles.SingleOrDefault(t => t.TitleId == itemToRemove);
Try
Title ttl = cartItems.SingleOrDefault(t => t.TitleId == itemToRemove);
i.e. instead of searching for the Title in 'ebs' (not sure what it contains, as not clear in OP code), search for items in Session Object directly and then remove it.
The .Remove() method is going to check for equality when trying to remove the item. Does Title implement IEquatable<Title>? If not then the check for equality is going to be default, which for objects is reference equality. And it's unlikely that reference equality is being satisfied here.
Implementing IEquatable<Title> is probably the ideal approach here. Just add that interface to the Title implementation and implement its one method:
public bool Equals(Title other)
{
if (other == null)
return false;
if (this.SomeValue == other.SomeValue)
return true;
else
return false;
}
This would put the equality logic on the model where it belongs. Failing that, your code would have to be more procedural in checking for equality. That is, you'd first have to find the element in cartItems that you're looking for and then remove that object, rather than trying to remove an object which itself exists in ebs.Titles. Something like:
cartItems.Remove(cartItems.Single(c => c.SomeValue == ttl.SomeValue));
That way the code is referencing the same in-memory object, not just an object that intuitively represents the same thing.

put LINQ code in sitecore code

I would to get "comment" by article ID . and i only can to get all comment in all article.
my plan is make LINQ code in my code
please check my code
var childrenss = new List<Sitecore.Data.Items.Item>();
foreach (var child in item.GetChildren())
{
childrenss.Add((Sitecore.Data.Items.Item)child);
}
any advice is appreciated. Thanks.
Well it looks like you should be able to use:
using System.Linq;
...
var children = item.GetChildren().ToList();
Ok I'm going to make a lot of assumptions here so if any of these are false and you need an explanation regarding any of the following let me know.
First of all I'm assuming your data in sitecore looks like this:
Video Item
Comment 1
Comment 2
Comment 3
Video Item 2
Comment 4
Comment 5
I also assume that you created a Sublayout that is meant to show the comments and that the Datasource of that Sublayout is a Video Item. (Incase this is not true you should consider it, integration of Sitecore DMS will later then be a lot easier)
In that case in your code behind of your sublayout there is no need to use any LINQ. You can simply use the following code:
public void Load_Page(object sender, EventArgs e)
{
Sublayout sublayout = Parent as Sublayout;
string datasource = sublayout.Datasource; // Contains Item GUID as string (if not using queries)
Item datasourceItem = Sitecore.Context.Database.GetItem(new ID(datasource));
Repeater.Datasource = datasourceItem.GetChildren();
Repeater.Databind();
}
So as you can see there's little to no reason at all to use any LINQ. For the sake of testing and argument you could demand that the Comment items are retrieved by using the Sitecore Index. To do that you can use the code from your other question.

help with expression for nHibernate linq provider extension

I'm working on a custom linq extension for nHibernate by extending the BaseHqlGeneratorForMethod. The technique is documented here:
http://fabiomaulo.blogspot.com/2010/07/nhibernate-linq-provider-extension.html
I've had success with implementing these for various types of operations, but I must say - converting a simple linq expression to its full expression tree is not easy! I'm stuck on one now.
For this example, I have three entities. Employee, Group, and EmployeeGroup. The EmployeeGroup class sets up a many-to-many relationship between Employee and Group. I must specifically create the intermediate class because there are additional properties to track like specific permissions each employee has in each group. So there are two one-to-many relationships, rather than an nHibernate many-to-many relationship.
Now say I want to get all groups that contain a specific employee. I can write this query:
var groups = session.Query<Group>()
.Where(g => g.EmployeeGroups.Any(eg => eg.Employee == employee));
This works fine, but it's a lot to type. I'd much rather be able to do this:
var groups = session.Query<Group>().Where(g => g.HasEmployee(employee));
I start by creating an extension method like so:
public static bool HasEmployee(this Group group, Employee employee)
{
return group.EmployeeGroups.Any(eg => eg.Employee == employee);
}
This works when querying a local list of groups, but not against the nHibernate session. For that, I have to also create a linq extension and register it. Just like in the article (linked above), I create a GroupHasEmployeeGenerator class that extends BaseHqlGeneratorForMethod. I set its .SupportedMethods property to reference my HasEmployee extension method.
Where I get lost is in the override to BuildHql. The expression to build gets complicated pretty fast. I figure since I'm replacing the .Any clause - a good place to start is with the source for the built-in AnyHqlGenerator class. But that doesn't take into account that the source is a property of the original element, and it also doesn't take into account that I don't have a lambda expression to represent the where clause. I need to build these parts manually.
There's no point in posting my attempts so far, as they've all be quite far from anything that would work.
Will someone please help me convert this simple expression into the approprate set of methods for the BuildHql method override?
If there is any better documentation out there for this, please let me know. Thanks.
I know this question is a year old, but I ran into a very similar issue when implementing BaseHqlGeneratorForMethod today.
The input to BuildHql contains a collection of System.Linq.Expressions.Expression arguments that are passed to your extension method. Using these arguments, you can build an expression tree that represents the implementation of your extension method. If the resulting expression is something NHibernate.Linq supports, then you can transform that expression to a subtree of Hql using the provided IHqlExpressionVisitor.
In your example:
public static bool HasEmployee(this Group group, Employee employee)
{
return group.EmployeeGroups.Any(eg => eg.Employee == employee);
}
This would become something similar to this:
public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection<Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
{
var AnyMethod = EnumerableHelper.GetMethod("Any", new[] {typeof(IEnumerable<EmployeeGroup>), typeof(Func<EmployeeGroup, bool>)}, new[] {typeof(EmployeeGroup)});
var EmployeeGroupsProperty = ReflectionHelper.GetProperty<Group>(g => g.EmployeeGroups);
var EmployeeProperty = ReflectionHelper.GetProperty<EmployeeGroup>(eg => eg.Employee);
var EmployeeGroupParameter = Expression.Parameter(typeof(EmployeeGroup));
var EmployeeGroupPredicate = Expression.Lambda(Expression.Equal(Expression.MakeMemberAccess(EmployeeGroupParameter, EmployeeProperty), arguments[1]), EmployeeGroupParameter);
var CallExpression = Expression.Call(AnyMethod, Expression.MakeMemberAccess(arguments[0], EmployeeGroupsProperty), EmployeeGroupPredicate);
return visitor.Visit(CallExpression);
}
I can't really test this specific example, but the same approach worked for me when providing support for my own extension method.

LINQ to SQL many to many int ID array criteria query

Ok this should be really simple, but I am doing my head in here and have read all the articles on this and tried a variety of things, but no luck.
I have 3 tables in a classic many-to-many setup.
ITEMS
ItemID
Description
ITEMFEATURES
ItemID
FeatureID
FEATURES
FeatureID
Description
Now I have a search interface where you can select any number of Features (checkboxes).
I get them all nicely as an int[] called SearchFeatures.
I simply want to find the Items which have the Features that are contained in the SearchFeatures.
E.g. something like:
return db.Items.Where(x => SearchFeatures.Contains(x.ItemFeatures.AllFeatures().FeatureID))
Inside my Items partial class I have added a custom method Features() which simply returns all Features for that Item, but I still can't seem to integrate that in any usable way into the main LINQ query.
Grr, it's gotta be simple, such a 1 second task in SQL. Many thanks.
The following query will return the list of items based on the list of searchFeatures:
from itemFeature in db.ItemFeatures
where searchFeatures.Contains(itemFeature.FeatureID)
select itemFeature.Item;
The trick here is to start with the ItemFeatures table.
It is possible to search items that have ALL features, as you asked in the comments. The trick here is to dynamically build up the query. See here:
var itemFeatures = db.ItemFeatures;
foreach (var temp in searchFeatures)
{
// You will need this extra variable. This is C# magic ;-).
var searchFeature = temp;
// Wrap the collection with a filter
itemFeatures =
from itemFeature in itemFeatures
where itemFeature.FeatureID == searchFeature
select itemFeature;
}
var items =
from itemFeature in itemFeatures
select itemFeature.Item;

How to use Crystal Reports without a tightly-linked DB connection?

I'm learning to use Crystal Reports (with VB 2005).
Most of what I've seen so far involves slurping data directly from a database, which is fine if that's all you want to display in the report.
My DB has a lot of foreign keys, so the way I've tried to stay sane with presenting actual information in my app is to add extra members to my objects that contain strings (descriptions) of what the foreign keys represent. Like:
Class AssetIdentifier
Private ID_AssetIdentifier As Integer
Private AssetID As Integer
Private IdentifierTypeID As Integer
Private IdentifierType As String
Private IdentifierText As String
...
Here, IdentifierTypeID is a foreign key, and I look up the value in a different table and place it in IdentifierType. That way I have the text description right in the object and I can carry it around with the other stuff.
So, on to my Crystal Reports question.
Crystal Reports seems to make it straightforward to hook up to records in a particular table (especially with the Experts), but that's all you get.
Ideally, I'd like to make a list of my classes, like
Dim assetIdentifiers as New List(Of AssetIdentifier)
and pass that to a Crystal Report instead of doing a tight link to a particular DB, have most of the work done for me but leaving me to work around the part that it doesn't do. The closest I can see so far is an ADO.NET dataset, but even that seems far removed. I'm already handling queries myself fine: I have all kinds of functions that return List(Of Whatever) based on queries.
Is there an easy way to do this?
Thanks in advance!
UPDATE: OK, I found something here:
http://msdn.microsoft.com/en-us/library/ms227595(VS.80).aspx
but it only appears to give this capability for web projects or web applications. Am I out of luck if I want to integrate into a standalone application?
Go ahead and create the stock object as described in the link you posted and create the report (StockObjectsReport) as they specify. In this simplified example I simply add a report viewer (crystalReportViewer1) to a form (Form1) and then use the following code in the Form_Load event.
stock s1 = new stock("AWRK", 1200, 28.47);
stock s2 = new stock("CTSO", 800, 128.69);
stock s3 = new stock("LTWR", 1800, 12.95);
ArrayList stockValues = new ArrayList();
stockValues.Add(s1);
stockValues.Add(s2);
stockValues.Add(s3);
ReportDocument StockObjectsReport = new StockObjectsReport();
StockObjectsReport.SetDataSource(stockValues);
crystalReportViewer1.ReportSource = StockObjectsReport;
This should populate your report with the 3 values from the stock object in a Windows Form.
EDIT: Sorry, I just realized that your question was in VB, but my example is in C#. You should get the general idea. :)
I'm loading the report by filename and it is working perfect:
//........
ReportDocument StockObjectsReport;
string reportPath = Server.MapPath("StockObjectsReport.rpt");
StockObjectsReport.Load(reportPath);
StockObjectsReport.SetDataSource(stockValues);
//Export PDF To Disk
string filePath = Server.MapPath("StockObjectsReport.pdf");
StockObjectsReport.ExportToDisk(ExportFormatType.PortableDocFormat, filePath);
#Dusty had it. However in my case it turned out you had to wrap the object in a list even though it was a single item before I could get it to print. See full code example:
string filePath = null;
string fileName = null;
ReportDocument newDoc = new ReportDocument();
// Set Path to Report File
fileName = "JShippingParcelReport.rpt";
filePath = func.GetReportsDirectory();
// IF FILE EXISTS... THEN
string fileExists = filePath +#"\"+ fileName;
if (System.IO.File.Exists(fileExists))
{
// Must Convert Object to List for some crazy reason?
// See: https://stackoverflow.com/a/35055093/1819403
var labelList = new List<ParcelLabelView> { label };
newDoc.Load(fileExists);
newDoc.SetDataSource(labelList);
try
{
// Set User Selected Printer Name
newDoc.PrintOptions.PrinterName = report.Printer;
newDoc.PrintToPrinter(1, false, 0, 0); //copies, collated, startpage, endpage
// Save Printing
report.Printed = true;
db.Entry(report).State = System.Data.Entity.EntityState.Modified;
db.SaveChanges();
}
catch (Exception e2)
{
string err = e2.Message;
}
}

Resources