star870126 发表于 2015-6-6 12:45:37

Linq to MySql/Oracle/Postgres/Sqlite

  与NHibernate相比较,Linq可能并是领域模型的,有数据为中心的思维痕迹,但在语言集成性上面,是其它O/R方案没有可比性的,Linq不仅仅是为对象与关系转换而生,随着Linq技术的日渐成熟,将会在诸多方面有所表现。
  开源社区也非常看好Linq的发展前景,在Linq推出后开源界出现了数十种有关Linq的项目,比如DbLinq(Linq to MySql,Oracle,SQLite),Linq to NHibernate,甚至还有Linq to google等等,这些项目从不同的应用和不同的角度展示出Linq的魅力。
  因为关注mono原因,时不时会了解一下mono的最新进展,当然也非常想看到Linq在mono中的应用,不过在mono1.2.6并没有集成,在下一个版本中肯定会有所表现。在Miguel de Icaza的博客中提到了一个DbLinq2007项目,可能会用于mono,目前最高版本是v0.16,试了一下,在vs.net2008beta2环境中的确能用,可到http://code.google.com/p/dblinq2007/下载,目前下载量不到千人,可以先下载尝尝鲜。
  DbLinq2007项目包括DbLinq.SqlServer/DbLinq.MySql/DbLinq.Oracle/DbLinq.PostgreSql/
  DbLinq.Sqlite几个部分,各部分相对独立的,本人试用了DbLinq.PostgreSql和DbLinq.MySql感觉非常不错,使用非常方便,使用方式也差不多,同Ms的Linq to Sql也几乎没有什么区别。下面以Northwind数据库为例,仅介绍一下DbLinq.MySql的简单应用。
  一、在MySql中建立用户与数据库:
  1、建立用户LinqUser:
  CREATE USER 'LinqUser'@'%'; SET PASSWORD FOR 'LinqUser'@'%' = PASSWORD('LinqUser');
  
  ##
  GRANT Select, Insert, Update, Delete, EXECUTE ON `Northwind`.* TO 'LinqUser'@'%';
  FLUSH PRIVILEGES;
  2、以LinqUser登录建立数据库Northwind:
  /*
  MySQL Data Transfer
  Source Host: localhost
  Source Database: northwind
  Target Host: localhost
  Target Database: northwind
  Date: 2008-1-24 22:23:29
  */
  
  SET FOREIGN_KEY_CHECKS=0;
  -- ----------------------------
  -- Table structure for categories
  -- ----------------------------
  CREATE TABLE `categories` (
  `CategoryID` int(11) NOT NULL auto_increment,
  `CategoryName` varchar(15) NOT NULL,
  `Description` text,
  `Picture` blob,
  PRIMARY KEY(`CategoryID`)
  ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
  
  -- ----------------------------
  -- Table structure for customers
  -- ----------------------------
  CREATE TABLE `customers` (
  `CustomerID` varchar(5) NOT NULL,
  `CompanyName` varchar(40) NOT NULL default '',
  `ContactName` varchar(30) default NULL,
  `ContactTitle` varchar(30) default NULL,
  `Address` varchar(60) default NULL,
  `City` varchar(15) default NULL,
  `Region` varchar(15) default NULL,
  `PostalCode` varchar(10) default NULL,
  `Country` varchar(15) default NULL,
  `Phone` varchar(24) default NULL,
  `Fax` varchar(24) default NULL,
  PRIMARY KEY(`CustomerID`)
  ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
  
  -- ----------------------------
  -- Table structure for employees
  -- ----------------------------
  CREATE TABLE `employees` (
  `EmployeeID` int(11) NOT NULL auto_increment,
  `LastName` varchar(20) NOT NULL,
  `FirstName` varchar(10) NOT NULL,
  `Title` varchar(30) default NULL,
  `BirthDate` datetime default NULL,
  `HireDate` datetime default NULL,
  `Address` varchar(60) default NULL,
  `City` varchar(15) default NULL,
  `Region` varchar(15) default NULL,
  `PostalCode` varchar(10) default NULL,
  `Country` varchar(15) default NULL,
  `HomePhone` varchar(24) default NULL,
  `Photo` blob,
  `Notes` text,
  `ReportsTo` int(11) default NULL,
  PRIMARY KEY(`EmployeeID`),
  KEY `FK_Emp_ReportsToEmp` (`ReportsTo`),
  CONSTRAINT `employees_ibfk_1` FOREIGN KEY (`ReportsTo`) REFERENCES `employees` (`EmployeeID`)
  ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
  
  -- ----------------------------
  -- Table structure for employeeterritories
  -- ----------------------------
  CREATE TABLE `employeeterritories` (
  `EmployeeID` int(11) NOT NULL,
  `TerritoryID` varchar(20) NOT NULL,
  PRIMARY KEY(`EmployeeID`,`TerritoryID`),
  KEY `FK_empTerr_terr` (`TerritoryID`),
  CONSTRAINT `employeeterritories_ibfk_1` FOREIGN KEY (`EmployeeID`) REFERENCES `employees` (`EmployeeID`),
  CONSTRAINT `employeeterritories_ibfk_2` FOREIGN KEY (`TerritoryID`) REFERENCES `territories` (`TerritoryID`)
  ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
  
  -- ----------------------------
  -- Table structure for order details
  -- ----------------------------
  CREATE TABLE `order details` (
  `OrderID` int(11) NOT NULL,
  `ProductID` int(11) NOT NULL,
  `UnitPrice` decimal(10,0) NOT NULL,
  `Quantity` smallint(6) NOT NULL,
  `Discount` float NOT NULL,
  PRIMARY KEY(`OrderID`,`ProductID`)
  ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
  
  -- ----------------------------
  -- Table structure for orders
  -- ----------------------------
  CREATE TABLE `orders` (
  `OrderID` int(11) NOT NULL auto_increment,
  `CustomerID` varchar(5) default NULL,
  `EmployeeID` int(11) default NULL,
  `OrderDate` datetime default NULL,
  `RequiredDate` datetime default NULL,
  `ShippedDate` datetime default NULL,
  `ShipVia` int(11) default NULL,
  `Freight` decimal(10,0) default NULL,
  `ShipName` varchar(40) default NULL,
  `ShipAddress` varchar(60) default NULL,
  `ShipCity` varchar(15) default NULL,
  `ShipRegion` varchar(15) default NULL,
  `ShipPostalCode` varchar(10) default NULL,
  `ShipCountry` varchar(15) default NULL,
  PRIMARY KEY(`OrderID`),
  KEY `FK_orders_1` (`CustomerID`),
  KEY `FK_orders_emp` (`EmployeeID`),
  CONSTRAINT `FK_orders_1` FOREIGN KEY (`CustomerID`) REFERENCES `customers` (`CustomerID`),
  CONSTRAINT `FK_orders_emp` FOREIGN KEY (`EmployeeID`) REFERENCES `employees` (`EmployeeID`)
  ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
  
  -- ----------------------------
  -- Table structure for products
  -- ----------------------------
  CREATE TABLE `products` (
  `ProductID` int(11) NOT NULL auto_increment,
  `ProductName` varchar(40) NOT NULL default '',
  `SupplierID` int(11) default NULL,
  `CategoryID` int(11) default NULL,
  `QuantityPerUnit` varchar(20) default NULL,
  `UnitPrice` decimal(10,0) default NULL,
  `UnitsInStock` smallint(6) default NULL,
  `UnitsOnOrder` smallint(6) default NULL,
  `ReorderLevel` smallint(6) default NULL,
  `Discontinued` bit(1) NOT NULL,
  PRIMARY KEY(`ProductID`),
  KEY `FK_prod_catg` (`CategoryID`),
  KEY `FK_prod_supp` (`SupplierID`),
  CONSTRAINT `products_ibfk_1` FOREIGN KEY (`CategoryID`) REFERENCES `categories` (`CategoryID`),
  CONSTRAINT `products_ibfk_2` FOREIGN KEY (`SupplierID`) REFERENCES `suppliers` (`SupplierID`)
  ) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='Holds Products';
  
  -- ----------------------------
  -- Table structure for region
  -- ----------------------------
  CREATE TABLE `region` (
  `RegionID` int(11) NOT NULL auto_increment,
  `RegionDescription` varchar(50) NOT NULL,
  PRIMARY KEY(`RegionID`)
  ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
  
  -- ----------------------------
  -- Table structure for shippers
  -- ----------------------------
  CREATE TABLE `shippers` (
  `ShipperID` int(11) NOT NULL auto_increment,
  `CompanyName` varchar(40) NOT NULL,
  `Phone` varchar(24) default NULL,
  PRIMARY KEY(`ShipperID`)
  ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
  
  -- ----------------------------
  -- Table structure for suppliers
  -- ----------------------------
  CREATE TABLE `suppliers` (
  `SupplierID` int(11) NOT NULL auto_increment,
  `CompanyName` varchar(40) NOT NULL default '',
  `ContactName` varchar(30) default NULL,
  `ContactTitle` varchar(30) default NULL,
  `Address` varchar(60) default NULL,
  `City` varchar(15) default NULL,
  `Region` varchar(15) default NULL,
  `PostalCode` varchar(10) default NULL,
  `Country` varchar(15) default NULL,
  `Phone` varchar(24) default NULL,
  `Fax` varchar(24) default NULL,
  PRIMARY KEY(`SupplierID`)
  ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
  
  -- ----------------------------
  -- Table structure for territories
  -- ----------------------------
  CREATE TABLE `territories` (
  `TerritoryID` varchar(20) NOT NULL,
  `TerritoryDescription` varchar(50) NOT NULL,
  `RegionID` int(11) NOT NULL,
  PRIMARY KEY(`TerritoryID`),
  KEY `FK_Terr_Region` (`RegionID`),
  CONSTRAINT `territories_ibfk_1` FOREIGN KEY (`RegionID`) REFERENCES `region` (`RegionID`)
  ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
  
  -- ----------------------------
  -- Records
  -- ----------------------------
  INSERT INTO `categories` VALUES ('1', 'Beverages', 'Soft drinks, coffees, teas, beers, and ales', null);
  INSERT INTO `categories` VALUES ('2', 'Condiments', 'Sweet and savory sauces, relishes, spreads, and seasonings', null);
  INSERT INTO `customers` VALUES ('AIRBU', 'airbus', 'jacques', null, null, 'Paris', null, '10000', 'France', null, null);
  INSERT INTO `customers` VALUES ('ALFKI', 'Alfreds Futterkiste', 'Maria Anders', 'Sales Representative', null, 'Berlin', null, '12209', 'Germany', '030-0074321', null);
  INSERT INTO `customers` VALUES ('ATT__', 'ATT', 'bob', null, null, 'New York', null, '10021', 'USA', null, null);
  INSERT INTO `customers` VALUES ('BONAP', 'Bon something', 'Bon Boss', 'Sales Representative', null, 'Paris', null, '11109', 'France', '033-0074321', null);
  INSERT INTO `customers` VALUES ('BT___', 'BT', 'graeme', null, null, 'London', null, 'E14', 'U.K.', null, null);
  INSERT INTO `customers` VALUES ('UKMOD', 'MOD', '(secret)', null, null, 'London', null, 'E14', 'U.K.', null, null);
  INSERT INTO `customers` VALUES ('WARTH', 'Wartian Herkku', 'Pirkko Koskitalo', 'Accounting Manager', null, 'Oulu', null, '90110', 'Finland', '981-443655', null);
  INSERT INTO `employees` VALUES ('1', 'Fuller', 'Andrew', 'Vice President, Sales', '1954-01-01 00:00:00', '1989-01-01 00:00:00', '908 W. Capital Way', 'Tacoma', null, null, null, null, null, null, null);
  INSERT INTO `employees` VALUES ('2', 'Davolio', 'Nancy', 'Sales Representative', '1964-01-01 00:00:00', '1994-01-01 00:00:00', '507 - 20th Ave. E.Apt. 2A', 'Seattle', null, null, null, null, null, null, '1');
  INSERT INTO `employees` VALUES ('3', 'Builder', 'Bob', 'Handyman', '1964-01-01 00:00:00', '1994-01-01 00:00:00', '666 dark street', 'Seattle', null, null, null, null, null, null, '2');
  INSERT INTO `employeeterritories` VALUES ('2', 'US.Northwest');
  INSERT INTO `orders` VALUES ('1', 'AIRBU', '1', '2008-02-01 19:27:44', null, null, null, '21', null, null, null, null, null, null);
  INSERT INTO `orders` VALUES ('2', 'BT___', '1', '2008-02-01 19:27:44', null, null, null, '11', null, null, null, null, null, null);
  INSERT INTO `orders` VALUES ('3', 'BT___', '1', '2008-02-01 19:27:44', null, null, null, '12', null, null, null, null, null, null);
  INSERT INTO `orders` VALUES ('4', 'UKMOD', '1', '2008-02-01 19:27:44', null, null, null, '33', null, null, null, null, null, null);
  INSERT INTO `products` VALUES ('1', 'Pen', '1', null, '10', null, '12', '2', null, '');
  INSERT INTO `products` VALUES ('2', 'Bicycle', '1', null, '1', null, '6', '0', null, '');
  INSERT INTO `products` VALUES ('3', 'Phone', null, null, '3', null, '7', '0', null, '');
  INSERT INTO `products` VALUES ('4', 'SAM', null, null, '1', null, '51', '11', null, '');
  INSERT INTO `products` VALUES ('5', 'iPod', null, null, '0', null, '11', '0', null, '');
  INSERT INTO `products` VALUES ('6', 'Toilet Paper', null, null, '2', null, '0', '3', null, '');
  INSERT INTO `products` VALUES ('7', 'Fork', null, null, '5', null, '111', '0', null, '');
  INSERT INTO `products` VALUES ('8', 'Linq Book', '2', null, '1', null, '0', '26', null, '');
  INSERT INTO `region` VALUES ('1', 'North America');
  INSERT INTO `region` VALUES ('2', 'Europe');
  INSERT INTO `suppliers` VALUES ('1', 'alles AG', 'Harald Reitmeyer', 'Prof', 'Fischergasse 8', 'Heidelberg', 'B-W', null, 'Germany', null, null);
  INSERT INTO `suppliers` VALUES ('2', 'Microsoft', 'Mr Allen', 'Monopolist', '1 MS', 'Redmond', 'WA', null, 'USA', null, null);
  INSERT INTO `territories` VALUES ('US.Northwest', 'Northwest', '1');
  二、将数据库映射为Northwind.cs文件:
  在DbLinq2007项目SqlMetal文件夹中找到SqlMetal.exe文件,在DOS状态运行,格式为:
  SqlMetal.exe -provider=MySql -database:Northwind -server:localhost -user:LinqUser -password:LinqUser -namespace:nwind -code:c:\Northwind.cs –sprocs
  注:-namespace根据自己的实际项目而定。
  三、在vs.net2008中创建应用程序项目,没人不会步骤略。将刚生成的Northwind.cs拷到项目中来。添加引用DbLinq2007中的DbLinq.dll / DbLinq.MySql.dll / MySql.data.dll
  四、现在可以在自己的项目中使用Linq to MySql了:
  using MySql.Data.MySqlClient;
  ……
  string connStr =@"server=localhost;database=Northwind;user=LinqUser;pwd=LinqUser;port=3306";
  MySqlConnection conn = new MySqlConnection(connString);
  Northwind db = new Northwind(conn);
  var data=from p in db.Customers select new {p.CustomerID,p.Phone};
  ……
  在这里每次使用时要申明一个MySqlConnection比较麻烦。可以修改一下先前生成的文件Northwind.cs,
  在里面添加using MySql.Data.MySqlClient;
  增加一个新的无参数的构造函数
  public Northwind(): base( new MySqlConnection(@"server=localhost;database=Northwind;user=LinqUser;pwd=LinqUser;port=3306")) {
  
  }
  当然连接字符串也可以放在配置文件中。
  
  修改了Northwind.cs文件以后,使用时只需Northwind db=new Northwind()方便多了。
  
  通过试用DbLinq2007感觉不错,同时也认为还不够成熟,不够稳定,特别是如果你使用的是0.16以前的版本,发现db.customers.select(p=>p)正确,但db.customers.select(p=>new {p.customerID,p.Phone})出错,0.16这个问题已经解决了。目前还不敢在项目中实际应用,先玩一玩再说,DbLinq2007版本更新比较快,期待着更稳定的版本尽快推出。
  ------------------------------------------------------------------------------------------------------------------------------------------
  

我把bug提交给jiri,现在已经修改好了,反映够快的.
DbLinq2007现在已可以用于Mono了.
Mono2.0即将发布,期待着Mono商用的开始.删除|回复 2008-04-02 00:09


0.16又发现Bug:
var data = from p in db.Customers
         where new string[]{"ALFKI", "WARTH"}.Contains(p.CustomerID)
         select new { p.CustomerID, p.Country };
构建new string[]{"ALFKI", "WARTH"}时错误。只能改成下面方式:
string[] customerIDIn = { "ALFKI", "WARTH" };
var data = from p in db.Customers
         where customerIDIn.Contains(p.CustomerID)
         select new { p.CustomerID, p.Country };
转自:
页: [1]
查看完整版本: Linq to MySql/Oracle/Postgres/Sqlite