Linq+Xml学习笔记

 

      Linq是第一次接触,此前一直用个的sql。这次写一个WPF的小程序,WPF的绑定和一般C#程序的绑定不同,以往直接绑定到datatable上,很方便。WPF中多需要转换成对象集合,不方便,就在网上搜索了下Linq的用法,通过这个程序进行了一下整理。

      个人感觉,Linq对Xml的操作比Xpath对Xml的操作要方便,对数据库进行操作还是看个人的喜好了。Linq对多表的操作还是感觉相当麻烦的,我个人还是倾向sql。

      首先,我建立了一个Dataitem.xml的文件,放在bin目录下

      数据的操作无非就是读、写、删、改。新增了一个Linqtoxml的类,在类里添加了以下方法:

      加载文件:

 

public static string Getxmlfile()
{
return System.AppDomain.CurrentDomain.BaseDirectory+"Dataitem.xml";
}

 

 

  读:

 

代码
public static List<Dataitem> Getalldata()
{
XDocument doc
=XDocument.Load(Getxmlfile());
var items
=(from i in doc.Descendants("数据项") select i).Take(20);
List
<Dataitem> list=new List<Dataitem>();
foreach(var item in items)
{
XElement p
=item;
Dataitem it
=new Dataitem();
it.Id
=Convert.ToInt32(p.Attribute("编号").Value);
it.Client
= p.Element("客户").Value;
it.Product
= p.Element("产品").Value;
it.Batch
= p.Element("批次").Value;
it.Team
= p.Element("班组").Value;
it.Total
=Convert.ToDouble(p.Element("总数").Value);
it.Receive
=Convert.ToDouble(p.Element("接收").Value);
it.Inspection
=Convert.ToDouble(p.Element("实检").Value);
it.Bugnum
=Convert.ToDouble(p.Element("缺陷").Value);
it.Inspector
= p.Element("检验").Value;
it.Inspectionday
=p.Element("日期").Value;
it.Bugdescription
= p.Element("缺陷描述").Value;
it.Bugresponsible
= p.Element("责任人员").Value;
it.Bugwith
= p.Element("缺陷处理").Value;
list.Add(it);
}
return list;
}

 

       写:

 

代码
public static void Adddata(Dataitem it)
{
XDocument doc
=XDocument.Load(Getxmlfile());
XElement ele
=new XElement("数据项",
new XAttribute("编号",it.Id),
new XElement("客户",it.Client),
new XElement("产品",it.Product),
new XElement("批次",it.Batch),
new XElement("班组",it.Team),
new XElement("总数",it.Total),
new XElement("接收",it.Receive),
new XElement("实检",it.Inspection),
new XElement("缺陷",it.Bugnum),
new XElement("检验",it.Inspector),
new XElement("日期",it.Inspectionday),
new XElement("缺陷描述",it.Bugdescription),
new XElement("责任人员",it.Bugresponsible),
new XElement("缺陷处理",it.Bugwith)
);
doc.Root.AddFirst(ele);
doc.Save(Getxmlfile());
}

 

      删:

 

代码
public static void deldata(int id)
{
XDocument doc
=XDocument.Load(Getxmlfile());
var items
=from i in doc.Descendants("数据项") where Convert.ToInt32(i.Attribute("编号").Value)==id select i;
XElement p
=null;
foreach(var item in items)
{
p
=item;
}
p.Remove();
doc.Save(Getxmlfile());
}

 

      改:

 

代码
public static void editdata(Dataitem it)
{
XDocument doc
=XDocument.Load(Getxmlfile());
var items
=from i in doc.Descendants("数据项") where Convert.ToInt32(i.Attribute("编号").Value)==it.Id select i;
XElement p
=null;
foreach(var item in items)
{
p
=item;
}
p.SetElementValue(
"客户",it.Client);
p.SetElementValue(
"产品",it.Product);
p.SetElementValue(
"批次",it.Batch);
p.SetElementValue(
"班组",it.Team);
p.SetElementValue(
"总数",it.Total);
p.SetElementValue(
"接收",it.Receive);
p.SetElementValue(
"实检",it.Inspection);
p.SetElementValue(
"缺陷",it.Bugnum);
p.SetElementValue(
"检验",it.Inspector);
p.SetElementValue(
"日期",it.Inspectionday);
p.SetElementValue(
"缺陷描述",it.Bugdescription);
p.SetElementValue(
"责任人员",it.Bugresponsible);
p.SetElementValue(
"缺陷处理",it.Bugwith);
doc.Save(Getxmlfile());
}

 

      还有个是进行了一个分组的统计,这个用法和sql的语法是不一样的,综合了网上的代码(很多不能用)进行了修改,反正是可以用的。呵呵,能搞定才能松口气。

      分组汇总:

 

代码
public static List<Statresult> Statdata(DateTime dt1,DateTime dt2)
{
XDocument doc
=XDocument.Load(Getxmlfile());
var items
=from i in doc.Descendants("数据项")
where Convert.ToDateTime(i.Element("日期").Value)>=dt1 && Convert.ToDateTime(i.Element("日期").Value)<=dt2
group i by i.Element(
"客户").Value into k select new
{
client
=k.Key,
total
=k.Sum(m=>Convert.ToDouble(m.Element("总数").Value)),
receiv
=k.Sum(m=>Convert.ToDouble(m.Element("接收").Value)),
rates
=Math.Round(k.Sum(m=>Convert.ToDouble(m.Element("接收").Value))/k.Sum(m=>Convert.ToDouble(m.Element("总数").Value)),4)*100,
inspect
=k.Sum(m=>Convert.ToDouble(m.Element("实检").Value)),
bugs
=k.Sum(m=>Convert.ToDouble(m.Element("缺陷").Value)),
qualified
=Math.Round((k.Sum(m=>Convert.ToDouble(m.Element("实检").Value))-k.Sum(m=>Convert.ToDouble(m.Element("缺陷").Value))) /k.Sum(m=>Convert.ToDouble(m.Element("实检").Value)),4)*100
};
List
<Statresult> list=new List<Statresult>();
foreach(var item in items)
{
Statresult st
=new Statresult();
st.Client
=item.client;
st.Total
=item.total;
st.Receive
=item.receiv;
st.Rates
=item.rates;
st.Inspection
=item.inspect;
st.Bugnum
=item.bugs;
st.Qualified
=item.qualified;
list.Add(st);
}
return list;
}

 

      使用Linq还有一个问题,就是实现sql中的拼接字符串。比如要搜索,条件拼接后传给逻辑层的方法进行调用。Linq中where关键字后不能使用字符串,跟的是一个bool型的表达式。困扰了许久,只能把实现直接写在应用层,用的是Linq的Where方法。使用Linq的时候要注意,select、where等等都有大写开头的方法,和小写的关键字是不一样的,这也是我后来发现的。Linq里面的各种内置方法用的都是C#的,和sql不用,这点也要注意

      字符串的拼接的解决办法:

 

代码
private void butqry_Click(object sender, System.Windows.RoutedEventArgs e)
{
// TODO: Add event handler implementation here.
XDocument doc=XDocument.Load(Linqtoxml.Getxmlfile());
var items
=from i in doc.Descendants("数据项") select i;

if(txt14.Text.Trim() != "")
items
=items.Where(k=>k.Element("客户").Value.Contains(txt14.Text.Trim()));
if(txt15.Text.Trim() !="")
items
=items.Where(k=>k.Element("产品").Value.Contains(txt15.Text.Trim()));
if(txt16.Text.Trim() !="")
items
=items.Where(k=>k.Element("批次").Value.Contains(txt16.Text.Trim()));
if(r1.IsChecked.Value && txt17.Text.Trim() !="")
{
try
{
Convert.ToDateTime(txt17.Text.Trim());
items
=items.Where(k=>Convert.ToDateTime(k.Element("日期").Value)>=Convert.ToDateTime(txt17.Text.Trim()));
}
catch
{
MessageBox.Show(
"第4个文本框只能输入日期!","注意",MessageBoxButton.OK,MessageBoxImage.Information);
return;
}
}
else if(r2.IsChecked.Value && txt18.Text.Trim() !="")
{
try
{
Convert.ToDateTime(txt18.Text.Trim());
items
=items.Where(k=>Convert.ToDateTime(k.Element("日期").Value)<=Convert.ToDateTime(txt18.Text.Trim()));
}
catch
{
MessageBox.Show(
"第5个文本框只能输入日期!","注意",MessageBoxButton.OK,MessageBoxImage.Information);
return;
}
}
else if(r3.IsChecked.Value && txt17.Text.Trim() !="" && txt18.Text.Trim() != "")
{
try
{
Convert.ToDateTime(txt17.Text.Trim());
Convert.ToDateTime(txt18.Text.Trim());
items
=items.Where(k=>Convert.ToDateTime(k.Element("日期").Value)>=Convert.ToDateTime(txt17.Text.Trim()) &&
Convert.ToDateTime(k.Element(
"日期").Value)<=Convert.ToDateTime(txt18.Text.Trim()));
}
catch
{
MessageBox.Show(
"最后2个文本框只能输入日期!","注意",MessageBoxButton.OK,MessageBoxImage.Information);
return;
}
}
if(r4.IsChecked.Value)
items
=items.Where(k=>Convert.ToDouble(k.Element("缺陷").Value)<=0);
else if(r5.IsChecked.Value)
items
=items.Where(k=>Convert.ToDouble(k.Element("缺陷").Value)>0);

List
<Dataitem> list=new List<Dataitem>();
foreach(var item in items)
{
XElement p
=item;
Dataitem it
=new Dataitem();
it.Id
=Convert.ToInt32(p.Attribute("编号").Value);
it.Client
= p.Element("客户").Value;
it.Product
= p.Element("产品").Value;
it.Batch
= p.Element("批次").Value;
it.Team
= p.Element("班组").Value;
it.Total
=Convert.ToDouble(p.Element("总数").Value);
it.Receive
=Convert.ToDouble(p.Element("接收").Value);
it.Inspection
=Convert.ToDouble(p.Element("实检").Value);
it.Bugnum
=Convert.ToDouble(p.Element("缺陷").Value);
it.Inspector
= p.Element("检验").Value;
it.Inspectionday
=p.Element("日期").Value;
it.Bugdescription
= p.Element("缺陷描述").Value;
it.Bugresponsible
= p.Element("责任人员").Value;
it.Bugwith
= p.Element("缺陷处理").Value;
list.Add(it);
}
if(list!=null)
datamain.ItemsSource
=list;
else
MessageBox.Show(
"没有找到符合条件的数据!","注意",MessageBoxButton.OK,MessageBoxImage.Information);

 

      个人使用的一点总结,希望和刚接触的朋友一起学习

posted @ 2010-11-06 10:46  何苦上青天  Views(462)  Comments(0Edit  收藏  举报