LinqDataSource query help - linq-to-sql

I know LINQ doesn't have the SQL IN clause but rather uses "contains". Can I use this on a LinqDataSource? I want to write a simple query that is equivelent to this:
SELECT * FROM tableA
WHERE tableA.requestType NOT IN (5,6,7,8) AND
tableA.someBitField IS NULL.
Is this possible using the LinqDataSource out of the box?
Thanks for any pointers.
Cheers,
~ck in San Diego

Yes, quite possible. Just handle the Selecting event on the datasource. The LinqDataSoruce class page on MSDN contains a great example already. Modifying that:
public partial class Default3 : System.Web.UI.Page
{
int[] validRequestTypes = { 5, 6, 7, 8 };
protected void Page_Load(object sender, EventArgs e)
{
}
protected void LinqDataSource_Selecting(object sender, LinqDataSourceSelectEventArgs e)
{
using(var dc = new MyDataContext())
{
var qry = from item in dc.tableAs
where validRequestTypes.contains(item.requestType)
&& item.someBitField == null
select item;
e.Result = qry;
}
}
}

Related

For unknown reason, a button click closes my window. How can I fix this?

I am trying to replicate a simple addition of 2 entries with a button in Monodevelop (shown how to make it step-by-step) but somehow the window closes 2 seconds after pressing the button without actually changing anything.
The code for the button:
using Gtk;
using Frontend.ChatService;
public partial class MainWindow : Gtk.Window
{
public MainWindow() : base(Gtk.WindowType.Toplevel)
{
Build();
}
protected void OnDeleteEvent(object sender, DeleteEventArgs a)
{
Application.Quit();
a.RetVal = true;
}
protected void OnButton1Clicked(object sender, EventArgs e)
{
ChatService client = new ChatService();
int x = Int32.Parse(entry1.Text);
int y = Int32.Parse(entry2.Text);
int sum = client.Add(x, y);
entry1.Text = sum.ToString();
}
}
And the sum (which I tested and think works):
using System;
using System.Web;
using System.Web.Services;
namespace Backend
{
public class ChatService : System.Web.Services.WebService
{
[WebMethod]
public int Add(int x, int y)
{
return x + y;
}
}
}
I left the main file program.cs as generated and is:
using System;
using Gtk;
namespace Frontend
{
class MainClass
{
public static void Main(string[] args)
{
Application.Init();
MainWindow win = new MainWindow();
win.Show();
Application.Run();
}
}
}
The window does pop up as it should and shows no problem until the button is pressed.
Edit:
I forgot to run the backend / server part, which is why the function was not found... (beginners mistake I guess)
Works now
The problem is probably that your code throws an exception you are not aware of. The problem is in the code that handles the button being clicked.
protected void OnButton1Clicked(object sender, EventArgs e)
{
ChatService client = new ChatService();
int x = Int32.Parse(entry1.Text);
int y = Int32.Parse(entry2.Text);
int sum = client.Add(x, y);
entry1.Text = sum.ToString();
}
Let's go line by line:
ChatService client = new ChatService();
Here you are creating a new instance of what it seems to be a system service or maybe a web services. This could throw if the service is not known (in the former case), or if the connection is interrupted or does not reach a destination, etc., in the latter case.
These lines are also delicate:
int x = Int32.Parse(entry1.Text);
int y = Int32.Parse(entry2.Text);
They will throw in case the field entry1 or entry2 are empty, or contain a letter...
In order to manage these cases you need to add try... catch blocks in the appropriate places. Alternately, you can use Int32.TryParse.
For example, assuming the service is in the web:
protected void OnButton1Clicked(object sender, EventArgs e)
{
ChatService client;
int x;
int y;
try {
client = new ChatService();
} catch(HttpRequestException exc) {
client = null;
var dlg = new Gtk.MessageDialog(
this,
Gtk.DialogFlags.Modal,
Gtk.MessageType.Error,
Gtk.ButtonsType.Ok,
"Connection error"
);
dlg.Text = exc.Message;
dlg.Run();
dlg.Destroy();
}
if ( client != null ) {
if ( !int.TryParse( entry1.Text, out x) {
entry1.Text = "0";
x = 0;
}
if ( !int.TryParse( entry2.Text, out y) {
entry2.Text = "0";
y = 0;
}
int sum = client.Add(x, y);
entry1.Text = sum.ToString();
}
}
Getting code which correctly handles errors is always harder, of course.
Hope this helps.

passage of several Parameters for the same screen in WindowsPhone

Good evening everyone
I'm trying to pass two objects at the same screen over the error to pass the second. I would like to know how to treat this receipt on my main screen.
I will try to give an example below:
first send an object parameter for the screen client
private void btTelaPedido (object sender, TappedRoutedEventArgs e) {
Customer customer = new Customer ();
customer.custid = Convert.ToInt32 (tbCodCliente.Text);
cliente.razao = tbNomeCliente.Text;
Frame.Navigate (typeof (pedidoTelaCadastro), client);
        }
then go to another screen and send another object
  
private void listaProduto_SelectionChanged (object sender, SelectionChangedEventArgs e) {
            Product produtoEscolhido = (sender the ListView) .SelectedItem the product;
            Frame.Navigate (typeof (pedidoTelaCadastro), produtoEscolhido);
        }
and that is, to receive code on the main screen.
protected override void OnNavigatedTo (NavigationEventArgs e) {
            this.navigationHelper.OnNavigatedTo (e);
 ClienteRecebido customer = (customer) e.Parameter;
                tbIdCliente.Text = Convert.ToString (clienteRecebido.idCliente);
                tbCliente.Text = clienteRecebido.razao;
                tbDataPedido.Text = "01/01/2015";
            ProdutoRecebido product = (Product) e.Parameter;
            tbProduto.Text = Convert.ToString (produtoRecebido.descricao);
        }
I wonder how he treats
protected override void OnNavigatedTo(NavigationEventArgs e)
{
this.navigationHelper.OnNavigatedTo(e);
Customer clienteRecebido = e.Parameter as Customer;
if(clienteRecebido !=null)
{
tbIdCliente.Text = Convert.ToString (clienteRecebido.idCliente);
tbCliente.Text = clienteRecebido.razao;
tbDataPedido.Text = "01/01/2015";
}
else
{
ProdutoRecebido product = (Product) e.Parameter;
tbProduto.Text = Convert.ToString (produtoRecebido.descricao);
}
}

Wait until async operation ends Windows Phone

I am trying to parse some pois from a xml download from a server and I saw that it is done after the program continues in the main thread. I haven't found a way to solve it because I need it.
using System.Threading;
namespace XML_Parser
{
class XMLParserPOI_Wiki
{
private static XMLParserPOI_Wiki objSingle = new XMLParserPOI_Wiki();
public static XMLParserPOI_Wiki ObjSingle
{
get { return objSingle; }
set { objSingle = value; }
}
private List<POI> places;
public List<POI> Places
{
get { return places; }
}
private XMLParserPOI_Wiki()
{
}
public void parseWikitude(string url)
{
places = new List<POI>();
WebClient wc = new WebClient();
wc.DownloadStringCompleted += HttpsCompleted;
wc.DownloadStringAsync(new Uri(url));
}
private void HttpsCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error == null)
{
XDocument xdoc = XDocument.Parse(e.Result, LoadOptions.None);
XNamespace ns = "http://www.opengis.net/kml/2.2";
XNamespace ns2 = "http://www.openarml.org/wikitude/1.0";
var placemarkers = xdoc.Root.Descendants(ns + "Placemark");
places =
(from query in xdoc.Root.Descendants(ns + "Placemark")
select new POI
(
...
)).ToList();
System.Diagnostics.Debug.WriteLine("Lista");
System.Diagnostics.Debug.WriteLine(places.Count);
}
}
}
}
In my main class:
XMLParserPOI_Wiki parserXML = XMLParserPOI_Wiki.ObjSingle;
parserXML.parseWikitude("http://myurl.php");
System.Diagnostics.Debug.WriteLine("Lista de pois");
System.Diagnostics.Debug.WriteLine(parserXML.Places.Count);
for (int i = 0; i < parserXML.Places.Count; i++)
{
System.Diagnostics.Debug.WriteLine(parserXML.Places[i].getName());
}
It prints Lista de POis and 0, before Lista and X (number of pois)
I guess I should freeze main thread but I tried a couple of times with some examples and they didn't work.
Can you point me to any tutorial about this? More than get an answer I want to understand how to deal with this kind of operations
First of all, you don't want to block (freeze) the UI thread EVER!
This is called asynchronous programming. There are two things you can do to solve your problem (I recommend option 2!):
Use the classic callback model. You basically call some long operation on a background thread and give a function to it, to execute when the long operation is done. Here's how to do it in your case.
At the end of the HttpsCompleted method, invoke what you need on the UI Thread using:
Deployment.Current.Dispatcher.BeginInvoke(delegate() {
//The code here will be invoked on the UI thread
});
If you want to make the parseWikitude method reusable, you should pass an Action to it. This way you can call it from multiple places and tell it what to do on the UI thread when the parsing is done. Something like this:
public void parseWikitude(string url, Action callback) {
places = new List<POI>();
WebClient wc = new WebClient();
wc.DownloadStringCompleted += HttpsCompleted;
wc.DownloadStringAsync(new Uri(url), callback);
}
private void HttpsCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error == null)
{
...
var callback = (Action)e.UserState;
Deployment.Current.Dispatcher.BeginInvoke(callback);
}
}
//And then when you use it, you do it like that
parserXML.parseWikitude("http://myurl.php", delegate() {
//The code here will be executed on the UI thread, after the parsing is done
});
Use the (rather) new asnyc pattern in .NET. You should read about this, as it is one of the best features of .NET if you ask me. :) It basically does the callback thing automatically and makes the code a lot easier to read/maintain/work-with. Once you get used to it, that is.
Here's an example:
public Task<List<POI>> parseWikitude(string url) {
TaskCompletionSource<List<POI>> resultTaskSource = new TaskCompletionSource<List<POI>>();
WebClient wc = new WebClient();
wc.DownloadStringCompleted += HttpsCompleted;
wc.DownloadStringAsync(new Uri(url), resultTaskSource);
return resultTaskSource.Task;
}
private void HttpsCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error == null)
{
//If needed, run the code here in a background thread
//...
var resultTaskSource = (TaskCompletionSource<List<POI>>)e.UserState;
resultTaskSource.SetResult(places);
}
}
//And when you need to use it, do it like that (note, this must be invoked in an async method!)
var places = await parser.parseWikitude("http://myurl.php");
//The code here will be executed on the same thread when the parsing is done, but the thread will not be blocked while the download is happening.
So, these are the two ways you can handle it. Option one is old-school, classic and easy. Option two is the new and cool way of doing async stuff. It really is a must-know. Simplifies a lot of things once you get used to it.
P.S. Sorry if I got carried away. :D

Linq 2 SQL , insert Objects with associated child objects List into database , Silverlight RIA

I am doing small Silverlight app which will allow users to Create orders. I have created Linq 2 SQL dbml and dragged there my database tables, "Orders" and "OrderLines" , there is an association between them. Order.ID ~ OrderLine.OrderID, so then i created DomainService for my tables, where i enabled client access, it generated for me the methods, Insert,Update,Delete,Get, for Orders and OrderLines, now i am creating New Order from my silverlight application, the usercontrol looks like this:
public partial class NewOrderView : UserControl
{
public ObservableCollection<OrderLine> OrderLines { get; set; }
public NewOrderView()
{
InitializeComponent();
OrderLines = new ObservableCollection<OrderLine>();
dataGrid.ItemsSource = OrderLines;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
var order = new Order();
foreach (var orderLine in OrderLines)
{
order.OrderLines.Add(orderLine);
}
order.CompanyId = int.Parse(StaticContainer.CurrentUser.CompanyId.ToString());
order.CreationDate = DateTime.Now;
order.Status = "შეკვეთილი";
order.Id = 1;
var ctx = new EntreeDomainContext();
ctx.Orders.Add(order);
ctx.SubmitChanges();
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
StaticContainer.Navigation.Back();
}
private void Button_Click_2(object sender, RoutedEventArgs e)
{
StaticContainer.Navigation.LogOut();
}
private void AddProduct(object sender, ProductAdditionEventHandlerArgs args)
{
var result = OrderLines.Where(x => x.Item.itmKEY == args.Product.itmKEY).FirstOrDefault();
if(result==null)
OrderLines.Add(new OrderLine(){Item = args.Product});
}
}
and Domain Service Method:
public void InsertOrder(Order order)
{
Context.Orders.InsertOnSubmit(order);
Context.SubmitChanges();
}
i have put here break point, and the thread comes here , and everything dones ok. but after that in the database no order and no orderline exist. and output writes : "A first chance exception of type 'System.Data.SqlClient.SqlException' occurred in System.Data.Linq.dll"
what can i do?
please help, and thank you.
Are you creating OrderLines from scratch? If so, you need to make sure that if they're new, that you're calling Context.OrderLines.InsertOnSubmit(orderLine) for each OrderLine you're adding, or you'll get problems like this. Also, you should provide all exception details here...

Microsoft Reporting with Collection as DataSource

I'm working with MS Reporting Services. The underlying datasource is
IEnumerable<MyObject>, I'm not using DataSets.
Every MyObject has properties and some other IEnumerable collections.
In the report I want to display all the properties from MyObject and
the collections lists too.
I didn't know how to display this inner collections, so I've made a SubReport to which I passed the MyObject.Id so that the SubReport could retrieve the object by himself and Build a the DataSource for these inner collections.
I do this in this event.
myReportViewer.LocalReport.SubreportProcessing += new SubreportProcessingEventHandler(LocalReport_SubreportProcessing);
private void LocalReport_SubreportProcessing(object sender, SubreportProcessingEventArgs e)
{
int id;
if (e.Parameters.Count > 0 && int.TryParse(e.Parameters[0].Values[0], out id))
{
MyObject current = myObjects.Where(x => x.MyObject.Id == id).FirstOrDefault();
InnerListBindingSource.DataSource = current.InnerCollection;
e.DataSources.Add(new Microsoft.Reporting.WinForms.ReportDataSource(
"MyInnerCollectionDataSource", InnerListBindingSource));
}
}
But there is always "The SubReport could not be shown" in my Master Report.
(Master report - subreport are correctly binded)
Any Idea why? Or how to resolve this in a more elegant way ?
Thank you
OK.
So I went to this solution and it's working:
private IEnumerable<MyObject> myObjects;
public ReportViewerForm(IEnumerable<MyObject> myObjects)
{
InitializeComponent();
this.myObjects = myObjects;
this.WindowState = FormWindowState.Maximized;
ReportViewer reportViewer = new ReportViewer();
reportViewer.ProcessingMode = ProcessingMode.Local;
reportViewer.LocalReport.ReportEmbeddedResource = #"SomePath." + "Report1.rdlc";
/*reportViewer.LocalReport.ReportPath = #"SomePath\Report1.rdlc"; */
reportViewer.LocalReport.SubreportProcessing +=
new SubreportProcessingEventHandler(SubreportProcessingEventHandler);
reportViewer.LocalReport.DataSources.Add(
new ReportDataSource("MyDataSource", myObjects));
reportViewer.LocalReport.SetParameters(new List<ReportParameter>
{
new ReportParameter("param1", ..WhatEver..),
...
});
reportViewer.Dock = DockStyle.Fill;
this.panel1.Controls.Add(reportViewer);
reportViewer.RefreshReport();
}
void SubreportProcessingEventHandler(object sender, SubreportProcessingEventArgs e)
{
/* For example ID parsing.. when you have it defined in .rdlc file.. */
int id;
if (e.Parameters.Count > 0 && int.TryParse(e.Parameters[0].Values[0], out id))
{
MyObject current = myObjects.Where(x => x.MyObject.Id == id).FirstOrDefault();
e.DataSources.Add(new Microsoft.Reporting.WinForms.ReportDataSource(
"InnerListDataSource", current.InnerList));
}
}
If I understand you correctly, you have a structure that resembles a table. So why don't you take a DataTable? ReportingServices offers easy access to those.
Or did I get you wrong there?