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