LINQ体验(9)——LINQ to SQL语句之Insert/Update/Delete操作

LINQ体验(9)——LINQ to SQL语句之Insert/Update/Delete操作

我们继续讲解LINQ to SQL语句,这篇我们来讨论Insert/Update/Delete操作。这个在我们的程序中最为常用了。我们直接看例子。

Insert/Update/Delete操作

Insert

1.简单形式

说明:new一个对象,使用InsertOnSubmit方法将其加入到对应的集合中,使用SubmitChanges()提交到数据库。

NorthwindDataContext db = new NorthwindDataContext();
var newCustomer = new Customer
{
    CustomerID = "MCSFT",
    CompanyName = "Microsoft",
    ContactName = "John Doe",
    ContactTitle = "Sales Manager",
    Address = "1 Microsoft Way",
    City = "Redmond",
    Region = "WA",
    PostalCode = "98052",
    Country = "USA",
    Phone = "(425) 555-1234",
    Fax = null
};
db.Customers.InsertOnSubmit(newCustomer);
db.SubmitChanges();

2.一对多关系

说明:Category与Product是一对多的关系,提交Category(一端)的数据时,LINQ to SQL会自动将Product(多端)的数据一起提交。

var newCategory = new Category
{
    CategoryName = "Widgets",
    Description = "Widgets are the ……"
};
var newProduct = new Product
{
    ProductName = "Blue Widget",
    UnitPrice = 34.56M,
    Category = newCategory
};
db.Categories.InsertOnSubmit(newCategory);
db.SubmitChanges();

3.多对多关系

说明:在多对多关系中,我们需要依次提交。

var newEmployee = new Employee
{
    FirstName = "Kira",
    LastName = "Smith"
};
var newTerritory = new Territory
{
    TerritoryID = "12345",
    TerritoryDescription = "Anytown",
    Region = db.Regions.First()
};
var newEmployeeTerritory = new EmployeeTerritory
{
    Employee = newEmployee,
    Territory = newTerritory
};
db.Employees.InsertOnSubmit(newEmployee);
db.Territories.InsertOnSubmit(newTerritory);
db.EmployeeTerritories.InsertOnSubmit(newEmployeeTerritory);
db.SubmitChanges();

4.Override using Dynamic CUD

说明:CUD就是Create、Update、Delete的缩写。下面的例子就是新建一个ID(主键)为32的Region,不考虑数据库中有没有ID为32的数据,如果有则替换原来的数据,没有则插入。(不知道这样说对不对。大家指点一下)

Region nwRegion = new Region()
{
    RegionID = 32,
    RegionDescription = "Rainy"
};
db.Regions.InsertOnSubmit(nwRegion);
db.SubmitChanges();

Update

说明:更新操作,先获取对象,进行修改操作之后,直接调用SubmitChanges()方法即可提交。注意,这里是在同一个DataContext中,对于不同的DataContex看下面的讲解。

1.简单形式

Customer cust =
    db.Customers.First(c => c.CustomerID == "ALFKI");
cust.ContactTitle = "Vice President";
db.SubmitChanges();

2.多个项

var q = from p in db.Products
        where p.CategoryID == 1
        select p;
foreach (var p in q)
{
    p.UnitPrice += 1.00M;
}
db.SubmitChanges();

Delete

1.简单形式

说明:调用DeleteOnSubmit方法即可。

OrderDetail orderDetail =
    db.OrderDetails.First
    (c => c.OrderID == 10255 && c.ProductID == 36);
db.OrderDetails.DeleteOnSubmit(orderDetail);
db.SubmitChanges();

2.一对多关系

说明:Order与OrderDetail是一对多关系,首先DeleteOnSubmit其OrderDetail(多端),其次DeleteOnSubmit其Order(一端)。因为一端是主键。

var orderDetails =
    from o in db.OrderDetails
    where o.Order.CustomerID == "WARTH" &&
    o.Order.EmployeeID == 3
    select o;
var order =
    (from o in db.Orders
     where o.CustomerID == "WARTH" && o.EmployeeID == 3
     select o).First();
foreach (OrderDetail od in orderDetails)
{
    db.OrderDetails.DeleteOnSubmit(od);
}
db.Orders.DeleteOnSubmit(order);
db.SubmitChanges();

3.Inferred Delete(推断删除)

说明:Order与OrderDetail是一对多关系,在上面的例子,我们全部删除CustomerID为WARTH和EmployeeID为3 的数据,那么我们不须全部删除呢?例如Order的OrderID为10248的OrderDetail有很多,但是我们只要删除ProductID为11的OrderDetail。这时就用Remove方法。

Order order = db.Orders.First(x => x.OrderID == 10248);
OrderDetail od = 
    order.OrderDetails.First(d => d.ProductID == 11);
order.OrderDetails.Remove(od);
db.SubmitChanges();

Update with Attach

说明:在对于在不同的DataContext之间,使用Attach方法来更新数据。例如在一个名为tempdb的NorthwindDataContext中,查询出Customer和Order,在另一个NorthwindDataContext中,Customer的地址更新为123 First Ave,Order的CustomerID 更新为CHOPS。

Customer c1;
List<Order> deserializedOrders = new List<Order>();
Customer deserializedC1;
using (NorthwindDataContext tempdb = new NorthwindDataContext())
{
    c1 = tempdb.Customers.Single(c => c.CustomerID == "ALFKI");
    deserializedC1 = new Customer
    {
        Address = c1.Address,
        City = c1.City,
        CompanyName = c1.CompanyName,
        ContactName = c1.ContactName,
        ContactTitle = c1.ContactTitle,
        Country = c1.Country,
        CustomerID = c1.CustomerID,
        Fax = c1.Fax,
        Phone = c1.Phone,
        PostalCode = c1.PostalCode,
        Region = c1.Region
    };
    Customer tempcust =
        tempdb.Customers.Single(c => c.CustomerID == "ANTON");
    foreach (Order o in tempcust.Orders)
    {
        deserializedOrders.Add(new Order
        {
            CustomerID = o.CustomerID,
            EmployeeID = o.EmployeeID,
            Freight = o.Freight,
            OrderDate = o.OrderDate,
            OrderID = o.OrderID,
            RequiredDate = o.RequiredDate,
            ShipAddress = o.ShipAddress,
            ShipCity = o.ShipCity,
            ShipName = o.ShipName,
            ShipCountry = o.ShipCountry,
            ShippedDate = o.ShippedDate,
            ShipPostalCode = o.ShipPostalCode,
            ShipRegion = o.ShipRegion,
            ShipVia = o.ShipVia
        });
    }
}
using (NorthwindDataContext db2 = new NorthwindDataContext())
{
    //对Customer更新,不能写错
    db2.Customers.Attach(deserializedC1);
    deserializedC1.Address = "123 First Ave";
    //对Order全部更新
    db2.Orders.AttachAll(deserializedOrders);
    foreach (Order o in deserializedOrders)
    {
        o.CustomerID = "CHOPS";
    }
    db2.SubmitChanges();
}

Update and Delete with Attach

说明:在不同的DataContext中,实现插入、更新、删除。看下面的一个例子:

Customer cust = null;
using (NorthwindDataContext tempdb = new NorthwindDataContext())
{
    cust = tempdb.Customers.First(x => x.CustomerID == "ALFKI");
}
Order orderA = cust.Orders.First();
Order orderB = cust.Orders.First(x => x.OrderID > orderA.OrderID);
using (NorthwindDataContext db2 = new NorthwindDataContext())
{
    db2.Customers.Attach(cust);
    db2.Orders.AttachAll(cust.Orders.ToList());
    //更新Customer的Phone.
    cust.Phone = "2345 5436";
    //更新OrderA的ShipCity.
    orderA.ShipCity = "Redmond";
    //删除OrderB.
    cust.Orders.Remove(orderB);
    //添加一个新的Order到Customer中.
    Order orderC = new Order() { ShipCity = "New York" };
    cust.Orders.Add(orderC);
    //提交执行
    db2.SubmitChanges();
}

本系列链接:LINQ体验系列文章导航


作者:李永京YJingLee's Blog
出处:http://lyj.cnblogs.com
转载请注明此处,谢谢!

Tag标签: LINQ,LINQ to SQL
posted @ 2008-01-28 14:03 李永京 阅读(4339) 评论(18)  编辑 收藏 所属分类: LINQ

  回复  引用  查看    
#1楼 2008-01-28 16:57 | 留恋星空      
我又来了
  回复  引用  查看    
#2楼 2008-01-28 16:57 | 高海东      
您好,请问下一对多和多对对如何保证事务呢?
  回复  引用  查看    
#3楼 [楼主]2008-01-28 17:20 | 李永京      
@留恋星空
继续来捧场子!
  回复  引用  查看    
#4楼 2008-01-28 20:23 | 笑疯^_^      
写的不错
  回复  引用  查看    
#5楼 [楼主]2008-01-31 17:31 | 李永京      
@高海东
他自动生成SQL语句吧,如果要事务可以加一个
using (TransactionScope ts = new TransactionScope()) {
try {
*************
db.SubmitChanges();
}
catch (System.Data.SqlClient.SqlException e) {
//执行异常处理
}
}

  回复  引用  查看    
#6楼 [楼主]2008-01-31 17:32 | 李永京      
@笑疯^_^
谢谢支持哦!!
  回复  引用  查看    
#7楼 2008-03-19 16:09 | A&Qiang      
我刚才测了一下多对多关系的插入操作,提交其中的任何一句在三个表中都能够插入对应的数据,不用将三条语句都提交,不知道你这样测过没有.
你的文章很好,继续努力!
  回复  引用  查看    
#8楼 [楼主]2008-03-19 16:53 | 李永京      
@A&Qiang
我这里测试也是的,这个例子是官方的实例。自己测试了,但是没有修改过再测试的。不知道怎么回事。常理说是一个一个提交的,难道在dbml文件中自动检测相关联表的内容。
  回复  引用  查看    
#9楼 2008-03-24 08:10 | inhesoft      
如何更新从视图查询出来的数据呢?还是使用Linq时根本不需要使用数据库视图?找不到相关的介绍!!!
  回复  引用  查看    
#10楼 [楼主]2008-03-24 09:28 | 李永京      
@inhesoft
LINQ支持视图的,同操作表类似。下例的Invoices就是视图。
var q =
from i in db.Invoices
where i.ShipCity == "London"
select new {i.OrderID, i.ProductName, i.Quantity, i.CustomerName};
具体接下来的文章介绍下。
  回复  引用  查看    
#11楼 2008-03-25 21:19 | A&Qiang      
碰到一个问题请指教:
在多对多的关系中,比如有三个表,一个user表, 一个group表,一个和这两个表相关联的UserGroup表.我想更改某一个用户的组的权限,将usergroup中EmpID=1,groupId=1的这一行数据更改为EmpID=1,groupId=2;进行了如下的操行:
var q =
from c in db.UserGroup
where c.EmpID == 1
select c;
foreach (var i in q)
{
i.GroupID= 2;
}

db.SubmitChanges();

但这样操作会报异常,异常为:
类型为“UserGroup”的对象的成员“GroupID”的值已更改。
无法更改定义对象标识的成员。
请改为考虑添加具有新标识的新对象,并删除现有的对象
意思好像说要先删除,再添加,请问为什么不能够直接修改呢.
谢谢!

  回复  引用  查看    
#12楼 [楼主]2008-03-25 22:13 | 李永京      
@A&Qiang
你这样写有问题的啊。在UserGroup表里有两个字段EmpID,GroupID(没有主键吧)。User表和Group表是多对多关系,在UserGroup表中不一定只有EmpID=1,GroupId=1这一记录,可能还有EmpID=1,GroupId=3;EmpID=1,GroupId=4等等,下面查询如果正确的话就把EmpID=1的记录的GroupId全部更新为2了。
应该先删除EmpID=1,GroupId=1这一记录,再添加EmpID=1,GroupId=2这一记录。
  回复  引用  查看    
#13楼 2008-03-26 08:07 | A&Qiang      
@李永京
是,我也知道存在这样的问题,我在表里只建了这么一条记录,我就是想测试一下为什么不能直接修改一行记录,必须先删除.比如我现在将where语句改成where c.EmpID == 1 && c.GroupID==1 这样写应该只找到这一条记录了吧,,但这样修改也出现同样的问题。
顺便说一下:我这个表里EmpID,GroupID是联合主键。
  回复  引用  查看    
#14楼 2008-03-26 15:58 | qinfeng520xian [未注册用户]
3.Inferred Delete(推断删除)
Order order = db.Orders.First(x => x.OrderID == 10248);
OrderDetail od = order.OrderDetails.First(d => d.ProductID == 11);
order.OrderDetails.Remove(od);
db.SubmitChanges();

产生异常
试图删除 Orders 和 Order_Details 之间的关系。但是,关系的其中一个外键 (Order_Details.OrderID) 无法设置为 null。

  回复  引用  查看    
#15楼 [楼主]2008-03-26 16:32 | 李永京      
@qinfeng520xian
我这里没有异常,你可能在数据库中没有OrderID等于10248的订单。换下一下数字试试啊