当有大量数据需要计算、显示在界面或者调用sleep函数时,容易导致界面卡死,可以采用多线程加委托的方法解决
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace WindowsFormsApplication1
{
public partial class FormMain : Form
{
DataTable table;
int currentIndex = 0;
int max = 10000;
public FormMain()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
button1.Enabled = false;
Thread thread = new Thread(new ThreadStart(LoadData));
thread.IsBackground = true;
thread.Start();
progressBar1.Minimum = 0;
progressBar1.Maximum = max;
}
private void LoadData()
{
SetLableText("数据加载中...");
currentIndex = 0;
table = new DataTable();
table.Columns.Add("id");
table.Columns.Add("name");
table.Columns.Add("age");
while (currentIndex < max)
{
SetLableText(string.Format("当前行:{0},剩余量:{1},完成比例:{2}%", currentIndex, max - currentIndex,
(Convert.ToDecimal(currentIndex) / Convert.ToDecimal(max) * 100).ToString("f0")));
SetPbValue(currentIndex);
DataRow dr = table.NewRow();
dr["id"] = currentIndex;
string name = "张三";
dr["name"] = name;
dr["age"] = currentIndex + 5;
table.Rows.Add(dr);
currentIndex++;
}
SetDgvDataSource(table);
SetLableText("数据加载完成!");
this.BeginInvoke(new MethodInvoker(delegate()
{
button1.Enabled = true;
}));
}
delegate void labDelegate(string str);
private void SetLableText(string str)
{
if (label1.InvokeRequired)
{
Invoke(new labDelegate(SetLableText), new string[] { str });
}
else
{
label1.Text = str;
}
}
delegate void dgvDelegate(DataTable table);
private void SetDgvDataSource(DataTable table)
{
if (dataGridView1.InvokeRequired)
{
Invoke(new dgvDelegate(SetDgvDataSource), new object[] { table });
}
else
{
dataGridView1.DataSource = table;
}
}
delegate void pbDelegate(int value);
private void SetPbValue(int value)
{
if (progressBar1.InvokeRequired)
{
Invoke(new pbDelegate(SetPbValue), new object[] { value });
}
else
{
progressBar1.Value = value;
}
}
}
}
运行效果图:
本文链接
去年在window service 插件服务插件开发时,曾经写过一篇.net 中读取自定义Config文件,那个配置文件通用读取方法,只适用于读取键值对,如下面示例所示:
<configuration>
<configSections>
<sectionGroup name="WeiboClientSectionGroup">
<section name="SinaSection" type="System.Configuration.NameValueSectionHandler,System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
<section name="QQSection" type="System.Configuration.NameValueSectionHandler,System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
<section name="SohuSection" type="System.Configuration.NameValueSectionHandler,System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
<section name="NetEaseSection" type="System.Configuration.NameValueSectionHandler,System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
</sectionGroup>
<sectionGroup name="WeiboSectionGroup">
<section name="SinaSection" type="System.Configuration.NameValueSectionHandler,System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
<section name="QQSection" type="System.Configuration.NameValueSectionHandler,System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
<section name="SohuSection" type="System.Configuration.NameValueSectionHandler,System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
<section name="NetEaseSection" type="System.Configuration.NameValueSectionHandler,System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
</sectionGroup>
</configSections>
<WeiboClientSectionGroup>
<SinaSection>
<add key="AccessToken" value=""/>
<add key="AccessTokenSecret" value=""/>
<add key="ResultFormat" value="Json"/>
</SinaSection>
<!--<QQSection> <add key="AccessToken" value=""/> <add key="AccessTokenSecret" value=""/> <add key="ResultFormat" value="Json"/> </QQSection>-->
<QQSection>
<add key="AccessToken" value=""/>
<add key="AccessTokenSecret" value=""/>
<add key="ResultFormat" value="Json"/>
</QQSection>
<SohuSection>
<add key="AccessToken" value=""/>
<add key="AccessTokenSecret" value=""/>
<add key="ResultFormat" value="Json"/>
</SohuSection>
<
很感谢王胖子2012同学的具体建议,从这次日记开始,我会在日记的开头介绍一下这篇日记的主要内容并给代码加高亮显示。
好的,让我们切入正题。这篇日记我将介绍Code First将类之间的引用关系映射为数据表之间的一对多关系的默认规则。主要包含以下两部分内容:
1.Code First将类之间的引用关系映射为数据表之间一对多关系的默认规则。
2.用Fluent API更改外键的nullable属性和外键的名字。
3.用Fluent API建立两个一对多数据表之间的多个外键。
4.用Fluent API设置级联删除功能。
1. Code First处理一对多关系的默认规则
在详细介绍Code First的默认规则之前,先让我们看两个示例,一个是一对多关系,另一个是多对多关系。
我在这个系列的日记中使用的示例是一个简单的订单管理系统。
在这个订单管理的业务中,我们有订单和订单条目两个实体。它们之间存在着一对多的关系;一个订单包含多个条目,一个条目只属于一个订单。
根据我们的业务逻辑我们建立了如下的两个类:
订单类:
public class Order{
public int OrderId { get; set; }
public DateTime CreatedDate { get; set; }
public Customer Customer { get; set; }
public List<OrderItem> OrderItems { get; set; }
public Order(){
OrderItems = new List<OrderItem>();
}
public void AddNewOrderItem(Product product, decimal retailPrice)
{
var item = new OrderItem();
item.Products = new List<Product>() { product };
item.RetailPrice = retailPrice;
item.Order = this;
OrderItems.Add(item);
}
public bool HasBuy(Product product)
{
bool hasBuy = false;
foreach (var item in OrderItems)
{
if (item.Products.Count > 0 && item.Products[0].Catalog.ProductCatalogId == product.Catalog.ProductCatalogId)
{
hasBuy = true;
break;
}
}
return hasBuy;
}
public void MergeOrderItem(Product product, decimal retailPrice, bool canMergeIfDifferencePrice)
{
foreach (var item in OrderItems)
{
if (item.Products.Count > 0 && item.Products[0].Catalog.ProductCatalogId == product.Catalog.ProductCatalogId)
{
if (item.RetailPrice != retailPrice && canMergeIfDifferencePrice == false)
{
throw new Exception("Can not merge items because they have different retail price");
}
item.RetailPrice = retailPrice;
item.Products.Add(product);
}
}
}
}
订单条目类:
public class OrderItem{
public int OrderItemId { get; set; }
public Order Order { get; set; }
public List<Product> Products { get; set; }public decimal RetailPrice { get; set; }
public OrderItem()
{
Products = new List<Product>();
}
}
大家可以注意一下在这两个类中标识为红颜色的部分,在订单类中有一个订单条目的集合,在订单条目类中有一个订单类的引用。
如果两个类互相包含另一个的实例或实例的集合,那么Code First就会默认为这两个表之间有一对多的关系,包含实例集合的类为主表,包含单个实例的类为子表。
我们修改一下自定义的可以插入基础数据的DropCreateOrderDatabaseWithSeedValueAlways类,插入一些产品目录,产品和客户的基础数据。
protected override void Seed(OrderSystemContext context){
context.ProductCatalogs.Add(new ProductCatalog { CatalogName = "DELL E6400", Manufactory = "DELL", ListPrice = 5600, NetPrice = 4300 });
context.ProductCatalogs.Add(new ProductCatalog { CatalogName = "DELL E6410", Manufactory = "DELL", ListPrice = 6500, NetPrice = 5100 });
context.ProductCatalogs.Add(new ProductCatalog { CatalogName = "DELL E6420", Manufactory = "DELL", ListPrice = 7000, NetPrice = 5400 });
context.Products.Add(new Product{ Catalog = new ProductCatalog { CatalogName = "DELL E6400", Manufactory = "DELL", ListPrice = 5600, NetPrice = 4300 }, CreateDate=DateTime.Parse("2010-1-20"), ExpireDate = DateTime.Parse("2013-1-20")});
context.Customers.Add(new Customer{IDCardNumber = "120104198106072518", CustomerName = "Alex", Gender = "M", PhoneNumber = "test" ,Address = new Address{Country = "China", Province = "Tianjin", City = "Tianjin", StreetAddress = "Crown Plaza", ZipCode = "300308" }});
}
然后我们可以写一个单元测试方法来测试一下Code First会建立怎样的一对多关系。
[TestMethod]
public void CanAddOrder()
{
OrderSystemContext unitOfWork = new OrderSystemContext();
ProductRepository productRepository = new ProductRepository(unitOfWork);
OrderRepository orderRepository = new OrderRepository(unitOfWork);
CustomerRepository customerRepository = new CustomerRepository(unitOfWork);
Order order = new Order { CreatedDate = DateTime.Now, Customer = cu