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);
个人使用的一点总结,希望和刚接触的朋友一起学习