diff --git a/Database/MySql/tracker.sql b/Database/MySql/tracker.sql
new file mode 100644
index 0000000..e49c4a0
--- /dev/null
+++ b/Database/MySql/tracker.sql
@@ -0,0 +1,473 @@
+SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
+SET time_zone = "+00:00";
+
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES utf8mb4 */;
+
+--
+-- Database: `tracker`
+--
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `audit`
+--
+
+DROP TABLE IF EXISTS `audit`;
+CREATE TABLE `audit` (
+ `Id` int(11) NOT NULL,
+ `Date` datetime NOT NULL,
+ `UserId` int(11) DEFAULT NULL,
+ `TaskId` int(11) DEFAULT NULL,
+ `Content` longtext NOT NULL,
+ `Username` varchar(50) NOT NULL,
+ `CreatedDate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `RowVersion` binary(8) NOT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `item`
+--
+
+DROP TABLE IF EXISTS `item`;
+CREATE TABLE `item` (
+ `ItemId` varchar(10) NOT NULL,
+ `ProductId` varchar(10) NOT NULL,
+ `ListPrice` decimal(10,2) DEFAULT NULL,
+ `UnitCost` decimal(10,2) DEFAULT NULL,
+ `Supplier` int(11) DEFAULT NULL,
+ `Status` varchar(2) DEFAULT NULL,
+ `Attr1` varchar(80) DEFAULT NULL,
+ `Attr2` varchar(80) DEFAULT NULL,
+ `Attr3` varchar(80) DEFAULT NULL,
+ `Attr4` varchar(80) DEFAULT NULL,
+ `Attr5` varchar(80) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+
+--
+-- Dumping data for table `item`
+--
+
+INSERT INTO `item` (`ItemId`, `ProductId`, `ListPrice`, `UnitCost`, `Supplier`, `Status`, `Attr1`, `Attr2`, `Attr3`, `Attr4`, `Attr5`) VALUES
+('EST-1', 'FI-SW-01', '16.50', '10.00', 1, 'P', 'Large', NULL, NULL, NULL, NULL),
+('EST-10', 'K9-DL-01', '18.50', '12.00', 1, 'P', 'Spotted Adult Female', NULL, NULL, NULL, NULL),
+('EST-11', 'RP-SN-01', '18.50', '12.00', 1, 'P', 'Venomless', NULL, NULL, NULL, NULL),
+('EST-12', 'RP-SN-01', '18.50', '12.00', 1, 'P', 'Rattleless', NULL, NULL, NULL, NULL),
+('EST-13', 'RP-LI-02', '18.50', '12.00', 1, 'P', 'Green Adult', NULL, NULL, NULL, NULL),
+('EST-14', 'FL-DSH-01', '58.50', '12.00', 1, 'P', 'Tailless', NULL, NULL, NULL, NULL),
+('EST-15', 'FL-DSH-01', '23.50', '12.00', 1, 'P', 'Tailed', NULL, NULL, NULL, NULL),
+('EST-16', 'FL-DLH-02', '93.50', '12.00', 1, 'P', 'Adult Female', NULL, NULL, NULL, NULL),
+('EST-17', 'FL-DLH-02', '93.50', '12.00', 1, 'P', 'Adult Male', NULL, NULL, NULL, NULL),
+('EST-18', 'AV-CB-01', '193.50', '92.00', 1, 'P', 'Adult Male', NULL, NULL, NULL, NULL),
+('EST-19', 'AV-SB-02', '15.50', '2.00', 1, 'P', 'Adult Male', NULL, NULL, NULL, NULL),
+('EST-2', 'FI-SW-01', '16.50', '10.00', 1, 'P', 'Small', NULL, NULL, NULL, NULL),
+('EST-20', 'FI-FW-02', '5.50', '2.00', 1, 'P', 'Adult Male', NULL, NULL, NULL, NULL),
+('EST-21', 'FI-FW-02', '5.29', '1.00', 1, 'P', 'Adult Female', NULL, NULL, NULL, NULL),
+('EST-22', 'K9-RT-02', '135.50', '100.00', 1, 'P', 'Adult Male', NULL, NULL, NULL, NULL),
+('EST-23', 'K9-RT-02', '145.49', '100.00', 1, 'P', 'Adult Female', NULL, NULL, NULL, NULL),
+('EST-24', 'K9-RT-02', '255.50', '92.00', 1, 'P', 'Adult Male', NULL, NULL, NULL, NULL),
+('EST-25', 'K9-RT-02', '325.29', '90.00', 1, 'P', 'Adult Female', NULL, NULL, NULL, NULL),
+('EST-26', 'K9-CW-01', '125.50', '92.00', 1, 'P', 'Adult Male', NULL, NULL, NULL, NULL),
+('EST-27', 'K9-CW-01', '155.29', '90.00', 1, 'P', 'Adult Female', NULL, NULL, NULL, NULL),
+('EST-28', 'K9-RT-01', '155.29', '90.00', 1, 'P', 'Adult Female', NULL, NULL, NULL, NULL),
+('EST-3', 'FI-SW-02', '18.50', '12.00', 1, 'P', 'Toothless', NULL, NULL, NULL, NULL),
+('EST-4', 'FI-FW-01', '18.50', '12.00', 1, 'P', 'Spotted', NULL, NULL, NULL, NULL),
+('EST-5', 'FI-FW-01', '18.50', '12.00', 1, 'P', 'Spotless', NULL, NULL, NULL, NULL),
+('EST-6', 'K9-BD-01', '18.50', '12.00', 1, 'P', 'Male Adult', NULL, NULL, NULL, NULL),
+('EST-7', 'K9-BD-01', '18.50', '12.00', 1, 'P', 'Female Puppy', NULL, NULL, NULL, NULL),
+('EST-8', 'K9-PO-02', '18.50', '12.00', 1, 'P', 'Male Puppy', NULL, NULL, NULL, NULL),
+('EST-9', 'K9-DL-01', '18.50', '12.00', 1, 'P', 'Spotless Male Puppy', NULL, NULL, NULL, NULL);
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `item 2`
+--
+
+DROP TABLE IF EXISTS `item 2`;
+CREATE TABLE `item 2` (
+ `ItemId` varchar(10) NOT NULL,
+ `ProductId` varchar(10) NOT NULL,
+ `ListPrice` decimal(10,2) DEFAULT NULL,
+ `UnitCost` decimal(10,2) DEFAULT NULL,
+ `Supplier` int(11) DEFAULT NULL,
+ `Status` varchar(2) DEFAULT NULL,
+ `Attr1` varchar(80) DEFAULT NULL,
+ `Attr2` varchar(80) DEFAULT NULL,
+ `Attr3` varchar(80) DEFAULT NULL,
+ `Attr4` varchar(80) DEFAULT NULL,
+ `Attr5` varchar(80) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `priority`
+--
+
+DROP TABLE IF EXISTS `priority`;
+CREATE TABLE `priority` (
+ `Id` int(11) NOT NULL,
+ `Name` varchar(50) NOT NULL,
+ `Order` int(11) NOT NULL,
+ `Description` varchar(200) DEFAULT NULL,
+ `CreatedDate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `ModifiedDate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `RowVersion` binary(8) NOT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+
+--
+-- Dumping data for table `priority`
+--
+
+INSERT INTO `priority` (`Id`, `Name`, `Order`, `Description`, `CreatedDate`, `ModifiedDate`, `RowVersion`) VALUES
+(1, 'High', 1, 'A High Priority', '2011-09-08 06:57:02', '2011-09-08 06:57:02', 0x00000000000007d1),
+(2, 'Normal', 2, 'A Normal Priority', '2011-09-08 06:57:02', '2011-09-08 06:57:02', 0x00000000000007d2),
+(3, 'Low', 3, 'A Low Priority', '2011-09-08 06:57:02', '2011-09-08 06:57:02', 0x00000000000007d3);
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `product`
+--
+
+DROP TABLE IF EXISTS `product`;
+CREATE TABLE `product` (
+ `ProductId` varchar(10) NOT NULL,
+ `Category` varchar(10) NOT NULL,
+ `Name` varchar(80) DEFAULT NULL,
+ `Descn` varchar(255) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+
+--
+-- Dumping data for table `product`
+--
+
+INSERT INTO `product` (`ProductId`, `Category`, `Name`, `Descn`) VALUES
+('AV-CB-01', 'BIRDS', 'Amazon Parrot', '
Great companion for up to 75 years'),
+('AV-SB-02', 'BIRDS', 'Finch', '
Great stress reliever'),
+('FI-FW-01', 'FISH', 'Koi', '
Freshwater fish from Japan'),
+('FI-FW-02', 'FISH', 'Goldfish', '
Freshwater fish from China'),
+('FI-SW-01', 'FISH', 'Angelfish', '
Saltwater fish from Australia'),
+('FI-SW-02', 'FISH', 'Tiger Shark', '
Saltwater fish from Australia'),
+('FL-DLH-02', 'CATS', 'Persian', '
Friendly house cat, doubles as a princess'),
+('FL-DSH-01', 'CATS', 'Manx', '
Great for reducing mouse populations'),
+('K9-BD-01', 'DOGS', 'Bulldog', '
Friendly dog from England'),
+('K9-CW-01', 'DOGS', 'Chihuahua', '
Great companion dog'),
+('K9-DL-01', 'DOGS', 'Dalmation', '
Great dog for a fire station'),
+('K9-PO-02', 'DOGS', 'Poodle', '
Cute dog from France'),
+('K9-RT-01', 'DOGS', 'Golden Retriever', '
Great family dog'),
+('K9-RT-02', 'DOGS', 'Labrador Retriever', '
Great hunting dog'),
+('RP-LI-02', 'REPTILES', 'Iguana', '
Friendly green friend'),
+('RP-SN-01', 'REPTILES', 'Rattlesnake', '
Doubles as a watch dog');
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `productsummary`
+--
+
+DROP TABLE IF EXISTS `productsummary`;
+CREATE TABLE `productsummary` (
+ `ProductId` varchar(10) NOT NULL,
+ `Name` varchar(80) DEFAULT NULL,
+ `AvgPrice` decimal(10,2) NOT NULL,
+ `Verified` tinyint(1) NOT NULL DEFAULT '1'
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `role`
+--
+
+DROP TABLE IF EXISTS `role`;
+CREATE TABLE `role` (
+ `Id` int(11) NOT NULL,
+ `Name` varchar(50) NOT NULL,
+ `Description` varchar(150) DEFAULT NULL,
+ `CreatedDate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `ModifiedDate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `RowVersion` binary(8) NOT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+
+--
+-- Dumping data for table `role`
+--
+
+INSERT INTO `role` (`Id`, `Name`, `Description`, `CreatedDate`, `ModifiedDate`, `RowVersion`) VALUES
+(1, 'Admin', NULL, '2011-09-08 06:57:02', '2011-09-08 06:57:02', 0x00000000000007d4),
+(2, 'Manager', NULL, '2011-09-08 06:57:02', '2011-09-08 06:57:02', 0x00000000000007d5),
+(3, 'Newb', NULL, '2011-09-08 06:57:02', '2011-09-08 06:57:02', 0x00000000000007d6),
+(4, 'Nobody', NULL, '2011-09-08 06:57:02', '2011-09-08 06:57:02', 0x00000000000007d7),
+(5, 'Power User', NULL, '2011-09-08 06:57:02', '2011-09-08 06:57:02', 0x00000000000007d8);
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `status`
+--
+
+DROP TABLE IF EXISTS `status`;
+CREATE TABLE `status` (
+ `Id` int(11) NOT NULL,
+ `Name` varchar(50) NOT NULL,
+ `Description` varchar(150) DEFAULT NULL,
+ `Order` int(11) NOT NULL,
+ `CreatedDate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `ModifiedDate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `RowVersion` binary(8) NOT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+
+--
+-- Dumping data for table `status`
+--
+
+INSERT INTO `status` (`Id`, `Name`, `Description`, `Order`, `CreatedDate`, `ModifiedDate`, `RowVersion`) VALUES
+(1, 'Not Started', NULL, 1, '2011-09-08 06:57:02', '2011-09-08 06:57:02', 0x00000000000007d9),
+(2, 'In Progress', NULL, 2, '2011-09-08 06:57:02', '2011-09-08 06:57:02', 0x00000000000007da),
+(3, 'Completed', NULL, 3, '2011-09-08 06:57:02', '2011-09-08 06:57:02', 0x00000000000007db),
+(4, 'Waiting on someone else', NULL, 4, '2011-09-08 06:57:02', '2011-09-08 06:57:02', 0x00000000000007dc),
+(5, 'Deferred', NULL, 5, '2011-09-08 06:57:02', '2011-09-08 06:57:02', 0x00000000000007dd),
+(6, 'Done', NULL, 6, '2011-09-08 06:57:02', '2011-09-08 06:57:02', 0x00000000000007de);
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `task`
+--
+
+DROP TABLE IF EXISTS `task`;
+CREATE TABLE `task` (
+ `Id` int(11) NOT NULL,
+ `StatusId` int(11) NOT NULL,
+ `PriorityId` int(11) DEFAULT NULL,
+ `CreatedId` int(11) NOT NULL,
+ `Summary` varchar(255) NOT NULL,
+ `Details` varchar(2000) DEFAULT NULL,
+ `StartDate` datetime DEFAULT NULL,
+ `DueDate` datetime DEFAULT NULL,
+ `CompleteDate` datetime DEFAULT NULL,
+ `AssignedId` int(11) DEFAULT NULL,
+ `CreatedDate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `ModifiedDate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `RowVersion` binary(8) NOT NULL,
+ `LastModifiedBy` varchar(50) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+
+--
+-- Dumping data for table `task`
+--
+
+INSERT INTO `task` (`Id`, `StatusId`, `PriorityId`, `CreatedId`, `Summary`, `Details`, `StartDate`, `DueDate`, `CompleteDate`, `AssignedId`, `CreatedDate`, `ModifiedDate`, `RowVersion`, `LastModifiedBy`) VALUES
+(1, 1, 1, 2, 'Make it to Earth', 'Find and make it to earth while avoiding the cylons.', NULL, NULL, NULL, 1, '2009-12-18 04:01:58', '2009-12-18 04:01:58', 0x00000000000007df, 'laura.roslin@battlestar.com');
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `taskextended`
+--
+
+DROP TABLE IF EXISTS `taskextended`;
+CREATE TABLE `taskextended` (
+ `TaskId` int(11) NOT NULL,
+ `Browser` varchar(200) DEFAULT NULL,
+ `OS` varchar(150) DEFAULT NULL,
+ `CreatedDate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `ModifiedDate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `RowVersion` binary(8) NOT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `user`
+--
+
+DROP TABLE IF EXISTS `user`;
+CREATE TABLE `user` (
+ `Id` int(11) NOT NULL,
+ `EmailAddress` varchar(250) NOT NULL,
+ `FirstName` varchar(200) DEFAULT NULL,
+ `LastName` varchar(200) DEFAULT NULL,
+ `Avatar` longblob,
+ `CreatedDate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `ModifiedDate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `RowVersion` binary(8) NOT NULL,
+ `PasswordHash` char(86) NOT NULL DEFAULT '',
+ `PasswordSalt` char(5) NOT NULL DEFAULT '',
+ `Comment` longtext,
+ `IsApproved` tinyint(1) NOT NULL DEFAULT '1',
+ `LastLoginDate` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
+ `LastActivityDate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `LastPasswordChangeDate` datetime DEFAULT NULL,
+ `AvatarType` varchar(150) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+
+--
+-- Dumping data for table `user`
+--
+
+INSERT INTO `user` (`Id`, `EmailAddress`, `FirstName`, `LastName`, `Avatar`, `CreatedDate`, `ModifiedDate`, `RowVersion`, `PasswordHash`, `PasswordSalt`, `Comment`, `IsApproved`, `LastLoginDate`, `LastActivityDate`, `LastPasswordChangeDate`, `AvatarType`) VALUES
+(1, 'william.adama@battlestar.com', 'William', 'Adama', NULL, '2009-05-06 10:46:20', '2009-05-06 10:46:20', 0x00000000000007e0, '1+v5rvSXnyX7tvwTKfM+aq+s0hDmNXsduGZfq8sQv1ggPnGlQdDdBdbUP0bUmbMbiU40PvRQWKRAy5QUd1xrAA', '?#nkY', NULL, 1, NULL, '2009-05-06 10:46:20', NULL, NULL),
+(2, 'laura.roslin@battlestar.com', 'Laura', 'Roslin', NULL, '2009-05-06 10:47:00', '2009-05-06 10:47:00', 0x00000000000007e1, 'Sx/jwRHFW/CQpO0E6G8d+jo344AmAKfX+C48a0iAZyMrb4sE8VoDuyZorbhbLZAX9f4UZk67O7eCjk854OrYSg', 'Ph)6;', NULL, 1, NULL, '2009-05-06 10:47:00', NULL, NULL),
+(3, 'kara.thrace@battlestar.com', 'Kara', 'Thrace', NULL, '2009-05-06 10:47:43', '2009-05-06 10:47:43', 0x00000000000007e2, '5KhtS4ax7G1aGkq97w02ooVZMmJp8bcySEKMSxruXu/Z/wRKoNAxMlkjRVY1yLavrC3GRYQZjy5b6JW8cR5EWg', '!]@2/', NULL, 1, NULL, '2009-05-06 10:47:43', NULL, NULL),
+(4, 'lee.adama@battlestar.com', 'Lee', 'Adama', NULL, '2009-05-06 10:48:02', '2009-05-06 10:48:02', 0x00000000000007e3, 'IrK8OhI2n4Ev3YA4y5kP7vy+n2CffX2MgcONbAh6/kZpNZYBYoYyrMhqdYztehL0NAIdvcInQ6zOjMplq+zWQA', 'e@_a{', NULL, 1, NULL, '2009-05-06 10:48:02', NULL, NULL),
+(5, 'gaius.baltar@battlestar.com', 'Gaius', 'Baltar', NULL, '2009-05-06 10:48:26', '2009-05-06 10:48:26', 0x00000000000007e4, '7tfajMaEerDNVgi6Oi6UJ6JxsUXZ0u4zQeUrZQxnaXJQ2f2vd9AzBR4sVOaH7LZtCjQopMzlQ38QqNEnpK0B/g', '_qpA2', NULL, 1, NULL, '2009-05-06 10:48:26', NULL, NULL),
+(6, 'saul.tigh@battlestar.com', 'Saul', 'Tigh', NULL, '2009-05-06 10:49:26', '2009-05-06 10:49:26', 0x00000000000007e5, 'wzkR89zRXe7hND1jqAP9xgupYJBvEZcjsfUe3TaU45kxRajjjS9u0fOTLK+uglzk67EGochJdeoikWs7hxMNRA', 'h]-zG', NULL, 1, NULL, '2009-05-06 10:49:26', NULL, NULL);
+
+--
+-- Indexes for dumped tables
+--
+
+--
+-- Indexes for table `audit`
+--
+ALTER TABLE `audit`
+ ADD PRIMARY KEY (`Id`),
+ ADD KEY `FK_Audit_Task` (`TaskId`),
+ ADD KEY `FK_Audit_User` (`UserId`);
+
+--
+-- Indexes for table `item`
+--
+ALTER TABLE `item`
+ ADD PRIMARY KEY (`ItemId`),
+ ADD KEY `FK__Item__ProductId__04E4BC85` (`ProductId`);
+
+--
+-- Indexes for table `item 2`
+--
+ALTER TABLE `item 2`
+ ADD PRIMARY KEY (`ItemId`),
+ ADD KEY `FK__Item 2__ProductI__0A9D95DB` (`ProductId`);
+
+--
+-- Indexes for table `priority`
+--
+ALTER TABLE `priority`
+ ADD PRIMARY KEY (`Id`);
+
+--
+-- Indexes for table `product`
+--
+ALTER TABLE `product`
+ ADD PRIMARY KEY (`ProductId`);
+
+--
+-- Indexes for table `productsummary`
+--
+ALTER TABLE `productsummary`
+ ADD PRIMARY KEY (`ProductId`);
+
+--
+-- Indexes for table `role`
+--
+ALTER TABLE `role`
+ ADD PRIMARY KEY (`Id`);
+
+--
+-- Indexes for table `status`
+--
+ALTER TABLE `status`
+ ADD PRIMARY KEY (`Id`);
+
+--
+-- Indexes for table `task`
+--
+ALTER TABLE `task`
+ ADD PRIMARY KEY (`Id`),
+ ADD KEY `IX_Task` (`AssignedId`,`StatusId`),
+ ADD KEY `FK_Task_Priority` (`PriorityId`),
+ ADD KEY `FK_Task_Status` (`StatusId`),
+ ADD KEY `FK_Task_User_Created` (`CreatedId`);
+
+--
+-- Indexes for table `taskextended`
+--
+ALTER TABLE `taskextended`
+ ADD PRIMARY KEY (`TaskId`);
+
+--
+-- Indexes for table `user`
+--
+ALTER TABLE `user`
+ ADD PRIMARY KEY (`Id`),
+ ADD UNIQUE KEY `IX_User` (`EmailAddress`);
+
+--
+-- AUTO_INCREMENT for dumped tables
+--
+
+--
+-- AUTO_INCREMENT for table `audit`
+--
+ALTER TABLE `audit`
+ MODIFY `Id` int(11) NOT NULL AUTO_INCREMENT;
+--
+-- AUTO_INCREMENT for table `role`
+--
+ALTER TABLE `role`
+ MODIFY `Id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=6;
+--
+-- AUTO_INCREMENT for table `status`
+--
+ALTER TABLE `status`
+ MODIFY `Id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=7;
+--
+-- AUTO_INCREMENT for table `task`
+--
+ALTER TABLE `task`
+ MODIFY `Id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;
+--
+-- AUTO_INCREMENT for table `user`
+--
+ALTER TABLE `user`
+ MODIFY `Id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=7;
+--
+-- Constraints for dumped tables
+--
+
+--
+-- Constraints for table `audit`
+--
+ALTER TABLE `audit`
+ ADD CONSTRAINT `FK_Audit_Task` FOREIGN KEY (`TaskId`) REFERENCES `task` (`Id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
+ ADD CONSTRAINT `FK_Audit_User` FOREIGN KEY (`UserId`) REFERENCES `user` (`Id`) ON DELETE NO ACTION ON UPDATE NO ACTION;
+
+--
+-- Constraints for table `item`
+--
+ALTER TABLE `item`
+ ADD CONSTRAINT `FK__Item__ProductId__04E4BC85` FOREIGN KEY (`ProductId`) REFERENCES `product` (`ProductId`) ON DELETE NO ACTION ON UPDATE NO ACTION;
+
+--
+-- Constraints for table `item 2`
+--
+ALTER TABLE `item 2`
+ ADD CONSTRAINT `FK__Item 2__ProductI__0A9D95DB` FOREIGN KEY (`ProductId`) REFERENCES `product` (`ProductId`) ON DELETE NO ACTION ON UPDATE NO ACTION;
+
+--
+-- Constraints for table `task`
+--
+ALTER TABLE `task`
+ ADD CONSTRAINT `FK_Task_Priority` FOREIGN KEY (`PriorityId`) REFERENCES `priority` (`Id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
+ ADD CONSTRAINT `FK_Task_Status` FOREIGN KEY (`StatusId`) REFERENCES `status` (`Id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
+ ADD CONSTRAINT `FK_Task_User_Assigned` FOREIGN KEY (`AssignedId`) REFERENCES `user` (`Id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
+ ADD CONSTRAINT `FK_Task_User_Created` FOREIGN KEY (`CreatedId`) REFERENCES `user` (`Id`) ON DELETE NO ACTION ON UPDATE NO ACTION;
+
+--
+-- Constraints for table `taskextended`
+--
+ALTER TABLE `taskextended`
+ ADD CONSTRAINT `FK_TaskExtended_Task` FOREIGN KEY (`TaskId`) REFERENCES `task` (`Id`) ON DELETE NO ACTION ON UPDATE NO ACTION;
+
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
diff --git a/Database/SqlServer/Tracker.sql b/Database/SqlServer/Tracker.sql
index 6dc6c92..ac6ff9c 100644
Binary files a/Database/SqlServer/Tracker.sql and b/Database/SqlServer/Tracker.sql differ
diff --git a/Database/SqlServer/Tracker/DacMetadata.xml b/Database/SqlServer/Tracker/DacMetadata.xml
new file mode 100644
index 0000000..392353a
--- /dev/null
+++ b/Database/SqlServer/Tracker/DacMetadata.xml
@@ -0,0 +1,5 @@
+
+
+ Tracker
+ 1.0.0.0
+
\ No newline at end of file
diff --git a/Database/SqlServer/Tracker/Origin.xml b/Database/SqlServer/Tracker/Origin.xml
new file mode 100644
index 0000000..8cd1b07
--- /dev/null
+++ b/Database/SqlServer/Tracker/Origin.xml
@@ -0,0 +1,22 @@
+
+
+
+ 3.0.0.0
+ false
+
+ 2.0.0.0
+ 1.0.0.0
+
+
+
+ b115af09-6ff8-4ee2-aa71-27c1b9dcda60
+ 2014-09-04T15:26:48.1499192-05:00
+ 2014-09-04T15:26:48.2608526-05:00
+ Microsoft.Data.Tools.Schema.Tasks.Sql, Version=12.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+ 12.0.40706.0
+ http://schemas.microsoft.com/sqlserver/dac/Serialization/2012/02
+
+
+ 4A52E1138674B39C68C0111BF1D1A0CA20D3D4633B60409E97BF619E229EF901
+
+
\ No newline at end of file
diff --git a/Database/SqlServer/Tracker/model.sql b/Database/SqlServer/Tracker/model.sql
new file mode 100644
index 0000000..3a3dac9
--- /dev/null
+++ b/Database/SqlServer/Tracker/model.sql
@@ -0,0 +1,123 @@
+CREATE TABLE [dbo].[Audit] (
+ [Id] INT IDENTITY (1, 1) NOT NULL,
+ [Date] DATETIME NOT NULL,
+ [UserId] INT NULL,
+ [TaskId] INT NULL,
+ [Content] VARCHAR (MAX) NOT NULL,
+ [Username] NVARCHAR (50) NOT NULL,
+ [CreatedDate] DATETIME CONSTRAINT [DF_Audit_CreatedDate] DEFAULT (getdate()) NOT NULL,
+ [RowVersion] ROWVERSION NOT NULL,
+ CONSTRAINT [PK_Audit] PRIMARY KEY CLUSTERED ([Id] ASC),
+ CONSTRAINT [FK_Audit_Task] FOREIGN KEY ([TaskId]) REFERENCES [dbo].[Task] ([Id]),
+ CONSTRAINT [FK_Audit_User] FOREIGN KEY ([UserId]) REFERENCES [dbo].[User] ([Id])
+);
+
+GO
+CREATE TABLE [dbo].[Priority] (
+ [Id] INT NOT NULL,
+ [Name] NVARCHAR (50) NOT NULL,
+ [Order] INT NOT NULL,
+ [Description] NVARCHAR (200) NULL,
+ [CreatedDate] DATETIME CONSTRAINT [DF__Priority__CreatedDate] DEFAULT (getdate()) NOT NULL,
+ [ModifiedDate] DATETIME CONSTRAINT [DF__Priority__ModifiedDate] DEFAULT (getdate()) NOT NULL,
+ [RowVersion] ROWVERSION NOT NULL,
+ CONSTRAINT [PK_Priority] PRIMARY KEY CLUSTERED ([Id] ASC)
+);
+
+GO
+CREATE TABLE [dbo].[Role] (
+ [Id] INT IDENTITY (1, 1) NOT NULL,
+ [Name] NVARCHAR (50) NOT NULL,
+ [Description] NVARCHAR (150) NULL,
+ [CreatedDate] DATETIME CONSTRAINT [DF__Role__CreatedDate] DEFAULT (getdate()) NOT NULL,
+ [ModifiedDate] DATETIME CONSTRAINT [DF__Role__ModifiedDate] DEFAULT (getdate()) NOT NULL,
+ [RowVersion] ROWVERSION NOT NULL,
+ CONSTRAINT [PK_Role] PRIMARY KEY CLUSTERED ([Id] ASC)
+);
+
+GO
+CREATE TABLE [dbo].[Status] (
+ [Id] INT IDENTITY (1, 1) NOT NULL,
+ [Name] NVARCHAR (50) NOT NULL,
+ [Description] NVARCHAR (150) NULL,
+ [Order] INT NOT NULL,
+ [CreatedDate] DATETIME CONSTRAINT [DF__Status__CreatedDate] DEFAULT (getdate()) NOT NULL,
+ [ModifiedDate] DATETIME CONSTRAINT [DF__Status__ModifiedDate] DEFAULT (getdate()) NOT NULL,
+ [RowVersion] ROWVERSION NOT NULL,
+ CONSTRAINT [PK_Status] PRIMARY KEY CLUSTERED ([Id] ASC)
+);
+
+GO
+CREATE TABLE [dbo].[Task] (
+ [Id] INT IDENTITY (1, 1) NOT NULL,
+ [StatusId] INT NOT NULL,
+ [PriorityId] INT NULL,
+ [CreatedId] INT NOT NULL,
+ [Summary] NVARCHAR (255) NOT NULL,
+ [Details] NVARCHAR (2000) NULL,
+ [StartDate] DATETIME NULL,
+ [DueDate] DATETIME NULL,
+ [CompleteDate] DATETIME NULL,
+ [AssignedId] INT NULL,
+ [CreatedDate] DATETIME CONSTRAINT [DF__Task__CreatedDate] DEFAULT (getdate()) NOT NULL,
+ [ModifiedDate] DATETIME CONSTRAINT [DF__Task__ModifiedDate] DEFAULT (getdate()) NOT NULL,
+ [RowVersion] ROWVERSION NOT NULL,
+ [LastModifiedBy] NVARCHAR (50) NULL,
+ CONSTRAINT [PK_Task] PRIMARY KEY CLUSTERED ([Id] ASC),
+ CONSTRAINT [FK_Task_Priority] FOREIGN KEY ([PriorityId]) REFERENCES [dbo].[Priority] ([Id]),
+ CONSTRAINT [FK_Task_Status] FOREIGN KEY ([StatusId]) REFERENCES [dbo].[Status] ([Id]),
+ CONSTRAINT [FK_Task_User_Assigned] FOREIGN KEY ([AssignedId]) REFERENCES [dbo].[User] ([Id]),
+ CONSTRAINT [FK_Task_User_Created] FOREIGN KEY ([CreatedId]) REFERENCES [dbo].[User] ([Id])
+);
+
+GO
+CREATE TABLE [dbo].[TaskExtended] (
+ [TaskId] INT NOT NULL,
+ [Browser] NVARCHAR (200) NULL,
+ [OS] NVARCHAR (150) NULL,
+ [CreatedDate] DATETIME DEFAULT (getdate()) NOT NULL,
+ [ModifiedDate] DATETIME DEFAULT (getdate()) NOT NULL,
+ [RowVersion] ROWVERSION NOT NULL,
+ CONSTRAINT [PK_TaskExtended] PRIMARY KEY CLUSTERED ([TaskId] ASC),
+ CONSTRAINT [FK_TaskExtended_Task] FOREIGN KEY ([TaskId]) REFERENCES [dbo].[Task] ([Id])
+);
+
+GO
+CREATE TABLE [dbo].[User] (
+ [Id] INT IDENTITY (1, 1) NOT NULL,
+ [EmailAddress] NVARCHAR (250) NOT NULL,
+ [FirstName] NVARCHAR (200) NULL,
+ [LastName] NVARCHAR (200) NULL,
+ [Avatar] VARBINARY (MAX) NULL,
+ [CreatedDate] DATETIME CONSTRAINT [DF__User__CreatedDate] DEFAULT (getdate()) NOT NULL,
+ [ModifiedDate] DATETIME CONSTRAINT [DF__User__ModifiedDate] DEFAULT (getdate()) NOT NULL,
+ [RowVersion] ROWVERSION NOT NULL,
+ [PasswordHash] CHAR (86) CONSTRAINT [DF__User__PasswordHash] DEFAULT ('') NOT NULL,
+ [PasswordSalt] CHAR (5) CONSTRAINT [DF__User__PasswordSalt] DEFAULT ('') NOT NULL,
+ [Comment] TEXT NULL,
+ [IsApproved] BIT CONSTRAINT [DF__User__IsApproved] DEFAULT ((1)) NOT NULL,
+ [LastLoginDate] DATETIME CONSTRAINT [DF__User__LastLoginDate] DEFAULT (getdate()) NULL,
+ [LastActivityDate] DATETIME CONSTRAINT [DF__User__LastActivityDate] DEFAULT (getdate()) NOT NULL,
+ [LastPasswordChangeDate] DATETIME NULL,
+ [AvatarType] NVARCHAR (150) NULL,
+ CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED ([Id] ASC)
+);
+
+GO
+CREATE TABLE [dbo].[UserRole] (
+ [UserId] INT NOT NULL,
+ [RoleId] INT NOT NULL,
+ CONSTRAINT [PK_UserRole] PRIMARY KEY CLUSTERED ([UserId] ASC, [RoleId] ASC),
+ CONSTRAINT [FK_UserRole_Role] FOREIGN KEY ([RoleId]) REFERENCES [dbo].[Role] ([Id]),
+ CONSTRAINT [FK_UserRole_User] FOREIGN KEY ([UserId]) REFERENCES [dbo].[User] ([Id])
+);
+
+GO
+CREATE NONCLUSTERED INDEX [IX_Task]
+ ON [dbo].[Task]([AssignedId] ASC, [StatusId] ASC);
+
+GO
+CREATE UNIQUE NONCLUSTERED INDEX [IX_User]
+ ON [dbo].[User]([EmailAddress] ASC);
+
+GO
diff --git a/Database/SqlServer/Tracker/model.xml b/Database/SqlServer/Tracker/model.xml
new file mode 100644
index 0000000..f07b170
--- /dev/null
+++ b/Database/SqlServer/Tracker/model.xml
@@ -0,0 +1,1925 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Database/SqlServer/Tracker/postdeploy.sql b/Database/SqlServer/Tracker/postdeploy.sql
new file mode 100644
index 0000000..b72b0b1
--- /dev/null
+++ b/Database/SqlServer/Tracker/postdeploy.sql
@@ -0,0 +1,471 @@
+/*
+Post-Deployment Script Template
+--------------------------------------------------------------------------------------
+ This file contains SQL statements that will be appended to the build script.
+ Use SQLCMD syntax to include a file in the post-deployment script.
+ Example: :r .\myfile.sql
+ Use SQLCMD syntax to reference a variable in the post-deployment script.
+ Example: :setvar TableName MyTable
+ SELECT * FROM [$(TableName)]
+--------------------------------------------------------------------------------------
+*/
+
+-- Table [dbo].[Priority] data
+MERGE INTO [dbo].[Priority] AS t
+USING
+(
+ VALUES
+ (
+ 1,
+ 'High',
+ 1,
+ 'A High Priority'
+ ),
+ (
+ 2,
+ 'Normal',
+ 2,
+ 'A Normal Priority'
+ ),
+ (
+ 3,
+ 'Low',
+ 3,
+ 'A Low Priority'
+ )
+)
+AS s
+(
+ [Id],
+ [Name],
+ [Order],
+ [Description]
+)
+ON
+(
+ t.[Id] = s.[Id]
+)
+WHEN NOT MATCHED BY TARGET THEN
+ INSERT
+ (
+ [Id],
+ [Name],
+ [Order],
+ [Description]
+ )
+ VALUES
+ (
+ s.[Id],
+ s.[Name],
+ s.[Order],
+ s.[Description]
+ )
+WHEN MATCHED THEN
+ UPDATE SET
+ t.[Name] = s.[Name],
+ t.[Order] = s.[Order],
+ t.[Description] = s.[Description]
+OUTPUT $action as [Action];
+
+
+SET IDENTITY_INSERT [dbo].[Role] ON
+
+-- Table [dbo].[Role] data
+MERGE INTO [dbo].[Role] AS t
+USING
+(
+ VALUES
+ (
+ 1,
+ 'Admin',
+ 'Admin Role'
+ ),
+ (
+ 2,
+ 'Manager',
+ NULL
+ ),
+ (
+ 3,
+ 'Newb',
+ NULL
+ ),
+ (
+ 4,
+ 'Nobody',
+ NULL
+ ),
+ (
+ 5,
+ 'Power User',
+ NULL
+ )
+)
+AS s
+(
+ [Id],
+ [Name],
+ [Description]
+)
+ON
+(
+ t.[Id] = s.[Id]
+)
+WHEN NOT MATCHED BY TARGET THEN
+ INSERT
+ (
+ [Id],
+ [Name],
+ [Description]
+ )
+ VALUES
+ (
+ s.[Id],
+ s.[Name],
+ s.[Description]
+ )
+WHEN MATCHED THEN
+ UPDATE SET
+ t.[Name] = s.[Name],
+ t.[Description] = s.[Description]
+OUTPUT $action as [Action];
+
+SET IDENTITY_INSERT [dbo].[Role] OFF
+
+
+SET IDENTITY_INSERT [dbo].[Status] ON
+
+-- Table [dbo].[Status] data
+MERGE INTO [dbo].[Status] AS t
+USING
+(
+ VALUES
+ (
+ 1,
+ 'Not Started',
+ NULL,
+ 1
+ ),
+ (
+ 2,
+ 'In Progress',
+ NULL,
+ 2
+ ),
+ (
+ 3,
+ 'Completed',
+ NULL,
+ 3
+ ),
+ (
+ 4,
+ 'Waiting on someone else',
+ NULL,
+ 4
+ ),
+ (
+ 5,
+ 'Deferred',
+ NULL,
+ 5
+ ),
+ (
+ 6,
+ 'Done',
+ NULL,
+ 6
+ )
+)
+AS s
+(
+ [Id],
+ [Name],
+ [Description],
+ [Order]
+)
+ON
+(
+ t.[Id] = s.[Id]
+)
+WHEN NOT MATCHED BY TARGET THEN
+ INSERT
+ (
+ [Id],
+ [Name],
+ [Description],
+ [Order]
+ )
+ VALUES
+ (
+ s.[Id],
+ s.[Name],
+ s.[Description],
+ s.[Order]
+ )
+WHEN MATCHED THEN
+ UPDATE SET
+ t.[Name] = s.[Name],
+ t.[Description] = s.[Description],
+ t.[Order] = s.[Order]
+OUTPUT $action as [Action];
+
+SET IDENTITY_INSERT [dbo].[Status] OFF
+
+
+SET IDENTITY_INSERT [dbo].[User] ON
+
+-- Table [dbo].[User] data
+MERGE INTO [dbo].[User] AS t
+USING
+(
+ VALUES
+ (
+ 1,
+ 'william.adama@battlestar.com',
+ 'William',
+ 'Adama',
+ NULL,
+ '1+v5rvSXnyX7tvwTKfM+aq+s0hDmNXsduGZfq8sQv1ggPnGlQdDdBdbUP0bUmbMbiU40PvRQWKRAy5QUd1xrAA',
+ '?#nkY',
+ 'Data Merge 635324524904242477',
+ 1,
+ '2014-04-07 07:26:54',
+ '2009-05-06 17:46:20',
+ NULL,
+ NULL
+ ),
+ (
+ 2,
+ 'laura.roslin@battlestar.com',
+ 'Laura',
+ 'Roslin',
+ NULL,
+ 'Sx/jwRHFW/CQpO0E6G8d+jo344AmAKfX+C48a0iAZyMrb4sE8VoDuyZorbhbLZAX9f4UZk67O7eCjk854OrYSg',
+ 'Ph)6;',
+ 'Data Merge 635324524904242477',
+ 1,
+ '2014-04-07 07:26:54',
+ '2009-05-06 17:47:00',
+ NULL,
+ NULL
+ ),
+ (
+ 3,
+ 'kara.thrace@battlestar.com',
+ 'Kara',
+ 'Thrace',
+ NULL,
+ '5KhtS4ax7G1aGkq97w02ooVZMmJp8bcySEKMSxruXu/Z/wRKoNAxMlkjRVY1yLavrC3GRYQZjy5b6JW8cR5EWg',
+ '!]@2/',
+ 'Data Merge 635324524147981355',
+ 1,
+ '2014-04-07 07:26:54',
+ '2009-05-06 17:47:43',
+ NULL,
+ NULL
+ ),
+ (
+ 4,
+ 'lee.adama@battlestar.com',
+ 'Lee',
+ 'Adama',
+ NULL,
+ 'IrK8OhI2n4Ev3YA4y5kP7vy+n2CffX2MgcONbAh6/kZpNZYBYoYyrMhqdYztehL0NAIdvcInQ6zOjMplq+zWQA',
+ 'e@_a{',
+ 'Data Merge 635324524147981355',
+ 1,
+ '2014-04-07 07:26:54',
+ '2009-05-06 17:48:02',
+ NULL,
+ NULL
+ ),
+ (
+ 5,
+ 'gaius.baltar@battlestar.com',
+ 'Gaius',
+ 'Baltar',
+ NULL,
+ '7tfajMaEerDNVgi6Oi6UJ6JxsUXZ0u4zQeUrZQxnaXJQ2f2vd9AzBR4sVOaH7LZtCjQopMzlQ38QqNEnpK0B/g',
+ '_qpA2',
+ 'Data Merge 635324524147981355',
+ 1,
+ '2014-04-07 07:26:54',
+ '2009-05-06 17:48:26',
+ NULL,
+ NULL
+ ),
+ (
+ 6,
+ 'saul.tigh@battlestar.com',
+ 'Saul',
+ 'Tigh',
+ NULL,
+ 'wzkR89zRXe7hND1jqAP9xgupYJBvEZcjsfUe3TaU45kxRajjjS9u0fOTLK+uglzk67EGochJdeoikWs7hxMNRA',
+ 'h]-zG',
+ 'Data Merge 635324524147981355',
+ 1,
+ '2014-04-07 07:26:54',
+ '2009-05-06 17:49:26',
+ NULL,
+ NULL
+ )
+)
+AS s
+(
+ [Id],
+ [EmailAddress],
+ [FirstName],
+ [LastName],
+ [Avatar],
+ [PasswordHash],
+ [PasswordSalt],
+ [Comment],
+ [IsApproved],
+ [LastLoginDate],
+ [LastActivityDate],
+ [LastPasswordChangeDate],
+ [AvatarType]
+)
+ON
+(
+ t.[Id] = s.[Id]
+)
+WHEN NOT MATCHED BY TARGET THEN
+ INSERT
+ (
+ [Id],
+ [EmailAddress],
+ [FirstName],
+ [LastName],
+ [Avatar],
+ [PasswordHash],
+ [PasswordSalt],
+ [Comment],
+ [IsApproved],
+ [LastLoginDate],
+ [LastActivityDate],
+ [LastPasswordChangeDate],
+ [AvatarType]
+ )
+ VALUES
+ (
+ s.[Id],
+ s.[EmailAddress],
+ s.[FirstName],
+ s.[LastName],
+ s.[Avatar],
+ s.[PasswordHash],
+ s.[PasswordSalt],
+ s.[Comment],
+ s.[IsApproved],
+ s.[LastLoginDate],
+ s.[LastActivityDate],
+ s.[LastPasswordChangeDate],
+ s.[AvatarType]
+ )
+WHEN MATCHED THEN
+ UPDATE SET
+ t.[EmailAddress] = s.[EmailAddress],
+ t.[FirstName] = s.[FirstName],
+ t.[LastName] = s.[LastName],
+ t.[Avatar] = s.[Avatar],
+ t.[PasswordHash] = s.[PasswordHash],
+ t.[PasswordSalt] = s.[PasswordSalt],
+ t.[Comment] = s.[Comment],
+ t.[IsApproved] = s.[IsApproved],
+ t.[LastLoginDate] = s.[LastLoginDate],
+ t.[LastActivityDate] = s.[LastActivityDate],
+ t.[LastPasswordChangeDate] = s.[LastPasswordChangeDate],
+ t.[AvatarType] = s.[AvatarType]
+OUTPUT $action as [Action];
+
+SET IDENTITY_INSERT [dbo].[User] OFF
+
+
+SET IDENTITY_INSERT [dbo].[Task] ON
+
+-- Table [dbo].[Task] data
+MERGE INTO [dbo].[Task] AS t
+USING
+(
+ VALUES
+ (
+ 1,
+ 1,
+ 1,
+ 2,
+ 'Make it to Earth',
+ 'Find and make it to earth while avoiding the cylons.',
+ NULL,
+ NULL,
+ NULL,
+ 1,
+ 'laura.roslin@battlestar.com'
+ )
+)
+AS s
+(
+ [Id],
+ [StatusId],
+ [PriorityId],
+ [CreatedId],
+ [Summary],
+ [Details],
+ [StartDate],
+ [DueDate],
+ [CompleteDate],
+ [AssignedId],
+ [LastModifiedBy]
+)
+ON
+(
+ t.[Id] = s.[Id]
+)
+WHEN NOT MATCHED BY TARGET THEN
+ INSERT
+ (
+ [Id],
+ [StatusId],
+ [PriorityId],
+ [CreatedId],
+ [Summary],
+ [Details],
+ [StartDate],
+ [DueDate],
+ [CompleteDate],
+ [AssignedId],
+ [LastModifiedBy]
+ )
+ VALUES
+ (
+ s.[Id],
+ s.[StatusId],
+ s.[PriorityId],
+ s.[CreatedId],
+ s.[Summary],
+ s.[Details],
+ s.[StartDate],
+ s.[DueDate],
+ s.[CompleteDate],
+ s.[AssignedId],
+ s.[LastModifiedBy]
+ )
+WHEN MATCHED THEN
+ UPDATE SET
+ t.[StatusId] = s.[StatusId],
+ t.[PriorityId] = s.[PriorityId],
+ t.[CreatedId] = s.[CreatedId],
+ t.[Summary] = s.[Summary],
+ t.[Details] = s.[Details],
+ t.[StartDate] = s.[StartDate],
+ t.[DueDate] = s.[DueDate],
+ t.[CompleteDate] = s.[CompleteDate],
+ t.[AssignedId] = s.[AssignedId],
+ t.[LastModifiedBy] = s.[LastModifiedBy]
+OUTPUT $action as [Action];
+
+SET IDENTITY_INSERT [dbo].[Task] OFF
+
+
+GO
diff --git a/License.txt b/License.txt
index cf68ccd..6704ab5 100644
--- a/License.txt
+++ b/License.txt
@@ -1,4 +1,5 @@
Copyright (c) 2012, LoreSoft
+Modified by AT Mulyana in 2016-2018
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
diff --git a/Source/EntityFramework.Extended.Test/EntityFramework.Extended.Test.net40.csproj b/Source/EntityFramework.Extended.Test/EntityFramework.Extended.Test.net40.csproj
index 78c0411..9ffc6b2 100644
--- a/Source/EntityFramework.Extended.Test/EntityFramework.Extended.Test.net40.csproj
+++ b/Source/EntityFramework.Extended.Test/EntityFramework.Extended.Test.net40.csproj
@@ -112,6 +112,9 @@
+
+
+
-
+
\ No newline at end of file
diff --git a/Source/EntityFramework.Extended/EntityFramework.Extended.net45.csproj b/Source/EntityFramework.Extended/EntityFramework.Extended.net45.csproj
index ddf8af6..aee8ce8 100644
--- a/Source/EntityFramework.Extended/EntityFramework.Extended.net45.csproj
+++ b/Source/EntityFramework.Extended/EntityFramework.Extended.net45.csproj
@@ -1,7 +1,7 @@
- Debug
+ Release
AnyCPU
8.0.30703
2.0
@@ -77,6 +77,8 @@
+
+
diff --git a/Source/EntityFramework.Extended/EntityFramework.Extended.nuspec b/Source/EntityFramework.Extended/EntityFramework.Extended.nuspec
index 4fa97e0..7cc3d69 100644
--- a/Source/EntityFramework.Extended/EntityFramework.Extended.nuspec
+++ b/Source/EntityFramework.Extended/EntityFramework.Extended.nuspec
@@ -1,20 +1,20 @@
- EntityFramework.Extended
- 6.1.0.0
- LoreSoft
- LoreSoft
- https://github.com/loresoft/EntityFramework.Extended
- https://github.com/loresoft/EntityFramework.Extended
+ EntityFrameworkExtended
+ 6.2.0.4
+ LoreSoft, AT Mulyana
+ LoreSoft, AT Mulyana
+ https://github.com/atmulyana/EntityFramework.Extended
+ https://github.com/atmulyana/EntityFramework.Extended
false
A library that extends the functionality of Entity Framework by adding batch update, future queries and audit logs.
Entity Framework extensions library.
- Copyright (c) 2014, LoreSoft
+ Copyright (c) 2014, LoreSoft, Modified by AT Mulyana in 2016-2018
en-US
EntityFramework
-
+
diff --git a/Source/EntityFramework.Extended/Extensions/BatchExtensions.cs b/Source/EntityFramework.Extended/Extensions/BatchExtensions.cs
index 8cb019f..7700d80 100644
--- a/Source/EntityFramework.Extended/Extensions/BatchExtensions.cs
+++ b/Source/EntityFramework.Extended/Extensions/BatchExtensions.cs
@@ -6,6 +6,7 @@
using System.Threading.Tasks;
using EntityFramework.Batch;
using EntityFramework.Mapping;
+using System.Collections.Generic;
namespace EntityFramework.Extensions
{
@@ -394,10 +395,220 @@ public static Task UpdateAsync(
var runner = ResolveRunner();
return runner.UpdateAsync(objectContext, entityMap, sourceQuery, updateExpression);
}
+#endif
+
+ private static Tuple GetQueryObjects(IDbSet dbSet) where TEntity : class
+ {
+ if (dbSet == null)
+ throw new ArgumentNullException("dbSet");
+
+ ObjectQuery destQuery = dbSet.ToObjectQuery();
+ if (destQuery == null)
+ throw new ArgumentException("The DbSet must be of type ObjectQuery or DbQuery.", "dbSet");
+
+ ObjectContext destContext = destQuery.Context;
+ if (destContext == null)
+ throw new ArgumentException("The ObjectContext for the DbSet can not be null.", "dbSet");
+
+ EntityMap entityMap = destQuery.GetEntityMap();
+ if (entityMap == null)
+ throw new ArgumentException("Could not load the entity mapping information for the destination.", "dbSet");
+ return Tuple.Create(destContext, entityMap);
+ }
+
+ private static Tuple, EntityMap> CheckDbQueryParams(IDbSet destination,
+ IQueryable source)
+ where TEntity : class
+ where TModel : class
+ {
+ EntityMap entityMap = GetQueryObjects(destination).Item2;
+
+ ObjectQuery sourceQuery = source.ToObjectQuery();
+ if (sourceQuery == null)
+ throw new ArgumentException("The query must be of type ObjectQuery or DbQuery.", "source");
+
+ ObjectContext sourceContext = sourceQuery.Context;
+ if (sourceContext == null)
+ throw new ArgumentException("The ObjectContext for the query can not be null.", "source");
+
+ return Tuple.Create(sourceQuery, entityMap);
+ }
+
+ ///
+ /// Executes a statement `INSERT INTO [Table] (...) SELECT ...
`.
+ ///
+ /// The type of the entity representing a record in database table.
+ /// The type of the query item.
+ /// The target table where the new data will be inserted into.
+ /// The query which retrieves the new data that will be inserted into the target table.
+ /// The number of row inserted.
+ /// Copy all items whose product id "K9-RT-02" from table item into item_2.
+ ///
+ ///
+ ///
+ /// When executing this method, the statement is immediately executed on the database provider
+ /// and is not part of the change tracking system. Also, changes will not be reflected on
+ /// any entities that have already been materialized in the current context.
+ ///
+ public static int Update(
+ this IDbSet destination,
+ IQueryable source)
+ where TEntity : class
+ where TModel : class
+ {
+ var p = CheckDbQueryParams(destination, source);
+ return ResolveRunner().Update(source, p.Item1, p.Item2);
+ }
+
+#if NET45
+ ///
+ /// Executes a statement `INSERT INTO [Table] (...) SELECT ...
` asynchronously.
+ ///
+ /// The type of the entity representing a record in database table.
+ /// The type of the query item.
+ /// The target table where the new data will be inserted into.
+ /// The query which retrieves the new data that will be inserted into the target table.
+ /// The number of row inserted.
+ /// Copy all items whose product id "K9-RT-02" from table item into item_2.
+ ///
+ ///
+ ///
+ /// When executing this method, the statement is immediately executed on the database provider
+ /// and is not part of the change tracking system. Also, changes will not be reflected on
+ /// any entities that have already been materialized in the current context.
+ ///
+ public static Task UpdateAsync(
+ this IDbSet destination,
+ IQueryable source)
+ where TEntity : class
+ where TModel : class
+ {
+ var p = CheckDbQueryParams(destination, source);
+ return ResolveRunner().UpdateAsync(source, p.Item1, p.Item2);
+ }
+#endif
+
+ ///
+ /// Executes a statement `INSERT INTO [Table] (...) SELECT ...
`.
+ ///
+ /// The type of the entity representing a record in database table.
+ /// The type of the query item.
+ /// The target table where the new data will be inserted into.
+ /// The query which retrieves the new data that will be inserted into the target table.
+ /// The number of row inserted.
+ /// Copy all items whose product id "K9-RT-02" from table item into item_2.
+ ///
+ ///
+ ///
+ /// When executing this method, the statement is immediately executed on the database provider
+ /// and is not part of the change tracking system. Also, changes will not be reflected on
+ /// any entities that have already been materialized in the current context.
+ ///
+ public static int Insert(
+ this IDbSet destination,
+ IQueryable source)
+ where TEntity : class
+ where TModel : class
+ {
+ var p = CheckDbQueryParams(destination, source);
+ return ResolveRunner().Insert(source, p.Item1, p.Item2);
+ }
+#if NET45
+ ///
+ /// Executes a statement `INSERT INTO [Table] (...) SELECT ...
` asynchronously.
+ ///
+ /// The type of the entity representing a record in database table.
+ /// The type of the query item.
+ /// The target table where the new data will be inserted into.
+ /// The query which retrieves the new data that will be inserted into the target table.
+ /// The number of row inserted.
+ /// Copy all items whose product id "K9-RT-02" from table item into item_2.
+ ///
+ ///
+ ///
+ /// When executing this method, the statement is immediately executed on the database provider
+ /// and is not part of the change tracking system. Also, changes will not be reflected on
+ /// any entities that have already been materialized in the current context.
+ ///
+ public static Task InsertAsync(
+ this IDbSet destination,
+ IQueryable source)
+ where TEntity : class
+ where TModel : class
+ {
+ var p = CheckDbQueryParams(destination, source);
+ return ResolveRunner().InsertAsync(source, p.Item1, p.Item2);
+ }
+#endif
+
+ ///
+ /// Inserts a lof of rows into a database table. It must be much faster than executing `DbSet.AddRange
` or
+ /// repetitive `DbSet.Add
` method and then executing 'DbContext.SaveChanges
' method.
+ ///
+ /// The type of objects representing rows to be inserted into db table.
+ /// The IDbSet
object representing the table to which the rows will be inserted.
+ /// The entity objects reprsenting the rows that will be inserted.
+ /// Number of rows in each batch. At the end of each batch, the rows in the batch are sent to the server. Zero means there
+ /// will be a single batch
+ /// Number of seconds for the operation to complete before it times out. Zero means no limit.
+ ///
+ /// The number of rows inserted.
+ ///
+ public static int Insert(this IDbSet dbSet, IEnumerable entities, int batchSize = 1000, int timeout = 0)
+ where TEntity : class
+ {
+ var objects = GetQueryObjects(dbSet);
+ return ResolveRunner().Insert(objects.Item1, entities, objects.Item2, batchSize, timeout);
+ }
+
+#if NET45
+ ///
+ /// Inserts a lof of rows into a database table asynchronously. It must be much faster than executing `DbSet.AddRange
` or
+ /// repetitive `DbSet.Add
` method and then executing 'DbContext.SaveChanges
' method.
+ ///
+ /// The type of objects representing rows to be inserted into db table.
+ /// The IDbSet
object representing the table to which the rows will be inserted.
+ /// The entity objects reprsenting the rows that will be inserted.
+ /// Number of rows in each batch. At the end of each batch, the rows in the batch are sent to the server. Zero means there
+ /// will be a single batch
+ /// Number of seconds for the operation to complete before it times out. Zero means no limit.
+ ///
+ /// The number of rows inserted.
+ ///
+ public static async Task InsertAsync(this IDbSet dbSet, IEnumerable entities, int batchSize = 1000, int timeout = 0)
+ where TEntity : class
+ {
+ var objects = GetQueryObjects(dbSet);
+ return await ResolveRunner().InsertAsync(objects.Item1, entities, objects.Item2, batchSize, timeout);
+ }
#endif
- private static IBatchRunner ResolveRunner()
+ internal static IBatchRunner ResolveRunner()
{
var provider = Locator.Current.Resolve();
if (provider == null)
diff --git a/Source/EntityFramework.Extended/Locator.cs b/Source/EntityFramework.Extended/Locator.cs
index 284dd0c..e669053 100644
--- a/Source/EntityFramework.Extended/Locator.cs
+++ b/Source/EntityFramework.Extended/Locator.cs
@@ -89,6 +89,7 @@ public static void RegisterDefaults(IContainer container)
{
container.Register(() => new MetadataMappingProvider());
container.Register(() => new SqlServerBatchRunner());
+ //container.Register(() => new MySqlBatchRunner());
container.Register(() => new FutureRunner());
container.Register(() => new MemoryCacheProvider());
diff --git a/Source/EntityFramework.Extended/Mapping/MetadataMappingProvider.cs b/Source/EntityFramework.Extended/Mapping/MetadataMappingProvider.cs
index 6c9235a..4d8b5b7 100644
--- a/Source/EntityFramework.Extended/Mapping/MetadataMappingProvider.cs
+++ b/Source/EntityFramework.Extended/Mapping/MetadataMappingProvider.cs
@@ -176,6 +176,7 @@ private static void SetProperties(EntityMap entityMap, EntitySetMapping mapping,
if (scalarPropertyMapping != null)
{
map.ColumnName = scalarPropertyMapping.Column.Name;
+ map.AutoGeneratedColumn = scalarPropertyMapping.Column.StoreGeneratedPattern != StoreGeneratedPattern.None;
continue;
}
@@ -239,7 +240,7 @@ private static void SetTableName(EntityMap entityMap)
private static string QuoteIdentifier(string name)
{
- return ("[" + name.Replace("]", "]]") + "]");
+ return Extensions.BatchExtensions.ResolveRunner().Quote(name);
}
}
}
\ No newline at end of file
diff --git a/Source/EntityFramework.Extended/Mapping/PropertyMap.cs b/Source/EntityFramework.Extended/Mapping/PropertyMap.cs
index abe0d78..d34d8c2 100644
--- a/Source/EntityFramework.Extended/Mapping/PropertyMap.cs
+++ b/Source/EntityFramework.Extended/Mapping/PropertyMap.cs
@@ -16,5 +16,9 @@ public class PropertyMap
/// Gets or sets the name of the column.
///
public string ColumnName { get; set; }
+ ///
+ /// Is it auto generated column, such as SQL Server Identity column?
+ ///
+ public bool AutoGeneratedColumn { get; set; }
}
}
\ No newline at end of file
diff --git a/Source/GlobalAssemblyInfo.net40.cs b/Source/GlobalAssemblyInfo.net40.cs
index d5ec530..62fcfe6 100644
--- a/Source/GlobalAssemblyInfo.net40.cs
+++ b/Source/GlobalAssemblyInfo.net40.cs
@@ -11,10 +11,10 @@
[assembly: System.Reflection.AssemblyProduct("EntityFramework.Extended (.NET 4.0)")]
[assembly: System.Reflection.AssemblyDescription("Entity Framework extensions library. Built for .NET 4.0")]
[assembly: System.Reflection.AssemblyCompany("LoreSoft")]
-[assembly: System.Reflection.AssemblyCopyright("Copyright © 2015 LoreSoft")]
+[assembly: System.Reflection.AssemblyCopyright("Copyright © 2015 LoreSoft, Modified by AT Mulyana in 2016-2018")]
[assembly: System.Reflection.AssemblyVersion("6.0.0.0")]
-[assembly: System.Reflection.AssemblyFileVersion("6.1.0.0")]
-[assembly: System.Reflection.AssemblyInformationalVersion("6.1.0.0")]
+[assembly: System.Reflection.AssemblyFileVersion("6.2.0.4")]
+[assembly: System.Reflection.AssemblyInformationalVersion("6.2.0.4")]
@@ -26,13 +26,13 @@ internal sealed partial class ThisAssembly {
internal const string AssemblyCompany = "LoreSoft";
- internal const string AssemblyCopyright = "Copyright © 2015 LoreSoft";
+ internal const string AssemblyCopyright = "Copyright © 2015 LoreSoft, Modified by AT Mulyana in 2016-2018";
internal const string AssemblyVersion = "6.0.0.0";
- internal const string AssemblyFileVersion = "6.1.0.0";
+ internal const string AssemblyFileVersion = "6.2.0.4";
- internal const string AssemblyInformationalVersion = "6.1.0.0";
+ internal const string AssemblyInformationalVersion = "6.2.0.4";
private ThisAssembly() {
}
diff --git a/Source/GlobalAssemblyInfo.net45.cs b/Source/GlobalAssemblyInfo.net45.cs
index 91700d4..1cbe846 100644
--- a/Source/GlobalAssemblyInfo.net45.cs
+++ b/Source/GlobalAssemblyInfo.net45.cs
@@ -11,10 +11,10 @@
[assembly: System.Reflection.AssemblyProduct("EntityFramework.Extended (.NET 4.5)")]
[assembly: System.Reflection.AssemblyDescription("Entity Framework extensions library. Built for .NET 4.5")]
[assembly: System.Reflection.AssemblyCompany("LoreSoft")]
-[assembly: System.Reflection.AssemblyCopyright("Copyright © 2015 LoreSoft")]
+[assembly: System.Reflection.AssemblyCopyright("Copyright © 2015 LoreSoft, Modified by AT Mulyana in 2016-2018")]
[assembly: System.Reflection.AssemblyVersion("6.0.0.0")]
-[assembly: System.Reflection.AssemblyFileVersion("6.1.0.0")]
-[assembly: System.Reflection.AssemblyInformationalVersion("6.1.0.0")]
+[assembly: System.Reflection.AssemblyFileVersion("6.2.0.4")]
+[assembly: System.Reflection.AssemblyInformationalVersion("6.2.0.4")]
@@ -26,13 +26,13 @@ internal sealed partial class ThisAssembly {
internal const string AssemblyCompany = "LoreSoft";
- internal const string AssemblyCopyright = "Copyright © 2015 LoreSoft";
+ internal const string AssemblyCopyright = "Copyright © 2015 LoreSoft, Modified by AT Mulyana in 2016-2018";
internal const string AssemblyVersion = "6.0.0.0";
- internal const string AssemblyFileVersion = "6.1.0.0";
+ internal const string AssemblyFileVersion = "6.2.0.4";
- internal const string AssemblyInformationalVersion = "6.1.0.0";
+ internal const string AssemblyInformationalVersion = "6.2.0.4";
private ThisAssembly() {
}
diff --git a/Source/Samples/net40/Tracker.SqlServer.Entities/Audit.cs b/Source/Samples/net40/Tracker.SqlServer.Entities/Audit.cs
index 4c21db4..1652bfe 100644
--- a/Source/Samples/net40/Tracker.SqlServer.Entities/Audit.cs
+++ b/Source/Samples/net40/Tracker.SqlServer.Entities/Audit.cs
@@ -1,3 +1,4 @@
+
//------------------------------------------------------------------------------
//
// This code was generated from a template.
@@ -7,23 +8,38 @@
//
//------------------------------------------------------------------------------
+
namespace Tracker.SqlServer.Entities
{
- using System;
+
+using System;
using System.Collections.Generic;
- public partial class Audit
- {
- public int Id { get; set; }
- public System.DateTime Date { get; set; }
- public Nullable UserId { get; set; }
- public Nullable TaskId { get; set; }
- public string Content { get; set; }
- public string Username { get; set; }
- public System.DateTime CreatedDate { get; set; }
- public byte[] RowVersion { get; set; }
-
- public virtual Task Task { get; set; }
- public virtual User User { get; set; }
- }
+public partial class Audit
+{
+
+ public int Id { get; set; }
+
+ public System.DateTime Date { get; set; }
+
+ public Nullable UserId { get; set; }
+
+ public Nullable TaskId { get; set; }
+
+ public string Content { get; set; }
+
+ public string Username { get; set; }
+
+ public System.DateTime CreatedDate { get; set; }
+
+ public byte[] RowVersion { get; set; }
+
+
+
+ public virtual Task Task { get; set; }
+
+ public virtual User User { get; set; }
+
+}
+
}
diff --git a/Source/Samples/net40/Tracker.SqlServer.Entities/Item.cs b/Source/Samples/net40/Tracker.SqlServer.Entities/Item.cs
new file mode 100644
index 0000000..2256104
--- /dev/null
+++ b/Source/Samples/net40/Tracker.SqlServer.Entities/Item.cs
@@ -0,0 +1,49 @@
+
+//------------------------------------------------------------------------------
+//
+// This code was generated from a template.
+//
+// Manual changes to this file may cause unexpected behavior in your application.
+// Manual changes to this file will be overwritten if the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+
+namespace Tracker.SqlServer.Entities
+{
+
+using System;
+ using System.Collections.Generic;
+
+public partial class Item
+{
+
+ public string ItemId { get; set; }
+
+ public string ProductId { get; set; }
+
+ public Nullable ListPrice { get; set; }
+
+ public Nullable UnitCost { get; set; }
+
+ public Nullable Supplier { get; set; }
+
+ public string Status { get; set; }
+
+ public string Attr1 { get; set; }
+
+ public string Attr2 { get; set; }
+
+ public string Attr3 { get; set; }
+
+ public string Attr4 { get; set; }
+
+ public string Attr5 { get; set; }
+
+
+
+ public virtual Product Product { get; set; }
+
+}
+
+}
diff --git a/Source/Samples/net40/Tracker.SqlServer.Entities/Item_2.cs b/Source/Samples/net40/Tracker.SqlServer.Entities/Item_2.cs
new file mode 100644
index 0000000..52feeaa
--- /dev/null
+++ b/Source/Samples/net40/Tracker.SqlServer.Entities/Item_2.cs
@@ -0,0 +1,49 @@
+
+//------------------------------------------------------------------------------
+//
+// This code was generated from a template.
+//
+// Manual changes to this file may cause unexpected behavior in your application.
+// Manual changes to this file will be overwritten if the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+
+namespace Tracker.SqlServer.Entities
+{
+
+using System;
+ using System.Collections.Generic;
+
+public partial class Item_2
+{
+
+ public string ItemId { get; set; }
+
+ public string ProductId { get; set; }
+
+ public Nullable ListPrice { get; set; }
+
+ public Nullable UnitCost { get; set; }
+
+ public Nullable Supplier { get; set; }
+
+ public string Status { get; set; }
+
+ public string Attr1 { get; set; }
+
+ public string Attr2 { get; set; }
+
+ public string Attr3 { get; set; }
+
+ public string Attr4 { get; set; }
+
+ public string Attr5 { get; set; }
+
+
+
+ public virtual Product Product { get; set; }
+
+}
+
+}
diff --git a/Source/Samples/net40/Tracker.SqlServer.Entities/Priority.cs b/Source/Samples/net40/Tracker.SqlServer.Entities/Priority.cs
index fad1458..8e20972 100644
--- a/Source/Samples/net40/Tracker.SqlServer.Entities/Priority.cs
+++ b/Source/Samples/net40/Tracker.SqlServer.Entities/Priority.cs
@@ -1,3 +1,4 @@
+
//------------------------------------------------------------------------------
//
// This code was generated from a template.
@@ -7,26 +8,42 @@
//
//------------------------------------------------------------------------------
+
namespace Tracker.SqlServer.Entities
{
- using System;
+
+using System;
using System.Collections.Generic;
- public partial class Priority
+public partial class Priority
+{
+
+ public Priority()
{
- public Priority()
- {
- this.Tasks = new HashSet();
- }
-
- public int Id { get; set; }
- public string Name { get; set; }
- public int Order { get; set; }
- public string Description { get; set; }
- public System.DateTime CreatedDate { get; set; }
- public System.DateTime ModifiedDate { get; set; }
- public byte[] RowVersion { get; set; }
-
- public virtual ICollection Tasks { get; set; }
+
+ this.Tasks = new HashSet();
+
}
+
+
+ public int Id { get; set; }
+
+ public string Name { get; set; }
+
+ public int Order { get; set; }
+
+ public string Description { get; set; }
+
+ public System.DateTime CreatedDate { get; set; }
+
+ public System.DateTime ModifiedDate { get; set; }
+
+ public byte[] RowVersion { get; set; }
+
+
+
+ public virtual ICollection Tasks { get; set; }
+
+}
+
}
diff --git a/Source/Samples/net40/Tracker.SqlServer.Entities/Product.cs b/Source/Samples/net40/Tracker.SqlServer.Entities/Product.cs
new file mode 100644
index 0000000..2366ea0
--- /dev/null
+++ b/Source/Samples/net40/Tracker.SqlServer.Entities/Product.cs
@@ -0,0 +1,47 @@
+
+//------------------------------------------------------------------------------
+//
+// This code was generated from a template.
+//
+// Manual changes to this file may cause unexpected behavior in your application.
+// Manual changes to this file will be overwritten if the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+
+namespace Tracker.SqlServer.Entities
+{
+
+using System;
+ using System.Collections.Generic;
+
+public partial class Product
+{
+
+ public Product()
+ {
+
+ this.Items = new HashSet- ();
+
+ this.Item_2 = new HashSet();
+
+ }
+
+
+ public string ProductId { get; set; }
+
+ public string Category { get; set; }
+
+ public string Name { get; set; }
+
+ public string Descn { get; set; }
+
+
+
+ public virtual ICollection
- Items { get; set; }
+
+ public virtual ICollection Item_2 { get; set; }
+
+}
+
+}
diff --git a/Source/Samples/net40/Tracker.SqlServer.Entities/ProductSummary.cs b/Source/Samples/net40/Tracker.SqlServer.Entities/ProductSummary.cs
new file mode 100644
index 0000000..9b8f007
--- /dev/null
+++ b/Source/Samples/net40/Tracker.SqlServer.Entities/ProductSummary.cs
@@ -0,0 +1,31 @@
+
+//------------------------------------------------------------------------------
+//
+// This code was generated from a template.
+//
+// Manual changes to this file may cause unexpected behavior in your application.
+// Manual changes to this file will be overwritten if the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+
+namespace Tracker.SqlServer.Entities
+{
+
+using System;
+ using System.Collections.Generic;
+
+public partial class ProductSummary
+{
+
+ public string ProductId { get; set; }
+
+ public string Name { get; set; }
+
+ public decimal AvgPrice { get; set; }
+
+ public bool Verified { get; set; }
+
+}
+
+}
diff --git a/Source/Samples/net40/Tracker.SqlServer.Entities/Role.cs b/Source/Samples/net40/Tracker.SqlServer.Entities/Role.cs
index 6b2b08f..1619326 100644
--- a/Source/Samples/net40/Tracker.SqlServer.Entities/Role.cs
+++ b/Source/Samples/net40/Tracker.SqlServer.Entities/Role.cs
@@ -1,3 +1,4 @@
+
//------------------------------------------------------------------------------
//
// This code was generated from a template.
@@ -7,25 +8,40 @@
//
//------------------------------------------------------------------------------
+
namespace Tracker.SqlServer.Entities
{
- using System;
+
+using System;
using System.Collections.Generic;
- public partial class Role
+public partial class Role
+{
+
+ public Role()
{
- public Role()
- {
- this.Users = new HashSet();
- }
-
- public int Id { get; set; }
- public string Name { get; set; }
- public string Description { get; set; }
- public System.DateTime CreatedDate { get; set; }
- public System.DateTime ModifiedDate { get; set; }
- public byte[] RowVersion { get; set; }
-
- public virtual ICollection Users { get; set; }
+
+ this.Users = new HashSet();
+
}
+
+
+ public int Id { get; set; }
+
+ public string Name { get; set; }
+
+ public string Description { get; set; }
+
+ public System.DateTime CreatedDate { get; set; }
+
+ public System.DateTime ModifiedDate { get; set; }
+
+ public byte[] RowVersion { get; set; }
+
+
+
+ public virtual ICollection Users { get; set; }
+
+}
+
}
diff --git a/Source/Samples/net40/Tracker.SqlServer.Entities/Status.cs b/Source/Samples/net40/Tracker.SqlServer.Entities/Status.cs
index 2468b9d..e1b566f 100644
--- a/Source/Samples/net40/Tracker.SqlServer.Entities/Status.cs
+++ b/Source/Samples/net40/Tracker.SqlServer.Entities/Status.cs
@@ -1,3 +1,4 @@
+
//------------------------------------------------------------------------------
//
// This code was generated from a template.
@@ -7,26 +8,42 @@
//
//------------------------------------------------------------------------------
+
namespace Tracker.SqlServer.Entities
{
- using System;
+
+using System;
using System.Collections.Generic;
- public partial class Status
+public partial class Status
+{
+
+ public Status()
{
- public Status()
- {
- this.Tasks = new HashSet();
- }
-
- public int Id { get; set; }
- public string Name { get; set; }
- public string Description { get; set; }
- public int Order { get; set; }
- public System.DateTime CreatedDate { get; set; }
- public System.DateTime ModifiedDate { get; set; }
- public byte[] RowVersion { get; set; }
-
- public virtual ICollection Tasks { get; set; }
+
+ this.Tasks = new HashSet();
+
}
+
+
+ public int Id { get; set; }
+
+ public string Name { get; set; }
+
+ public string Description { get; set; }
+
+ public int Order { get; set; }
+
+ public System.DateTime CreatedDate { get; set; }
+
+ public System.DateTime ModifiedDate { get; set; }
+
+ public byte[] RowVersion { get; set; }
+
+
+
+ public virtual ICollection Tasks { get; set; }
+
+}
+
}
diff --git a/Source/Samples/net40/Tracker.SqlServer.Entities/Task.cs b/Source/Samples/net40/Tracker.SqlServer.Entities/Task.cs
index cea704c..461c102 100644
--- a/Source/Samples/net40/Tracker.SqlServer.Entities/Task.cs
+++ b/Source/Samples/net40/Tracker.SqlServer.Entities/Task.cs
@@ -1,3 +1,4 @@
+
//------------------------------------------------------------------------------
//
// This code was generated from a template.
@@ -7,38 +8,66 @@
//
//------------------------------------------------------------------------------
+
namespace Tracker.SqlServer.Entities
{
- using System;
+
+using System;
using System.Collections.Generic;
- public partial class Task
+public partial class Task
+{
+
+ public Task()
{
- public Task()
- {
- this.Audits = new HashSet();
- }
-
- public int Id { get; set; }
- public int StatusId { get; set; }
- public Nullable PriorityId { get; set; }
- public int CreatedId { get; set; }
- public string Summary { get; set; }
- public string Details { get; set; }
- public Nullable StartDate { get; set; }
- public Nullable DueDate { get; set; }
- public Nullable CompleteDate { get; set; }
- public Nullable AssignedId { get; set; }
- public System.DateTime CreatedDate { get; set; }
- public System.DateTime ModifiedDate { get; set; }
- public byte[] RowVersion { get; set; }
- public string LastModifiedBy { get; set; }
-
- public virtual ICollection Audits { get; set; }
- public virtual Priority Priority { get; set; }
- public virtual Status Status { get; set; }
- public virtual User User { get; set; }
- public virtual User User1 { get; set; }
- public virtual TaskExtended TaskExtended { get; set; }
+
+ this.Audits = new HashSet();
+
}
+
+
+ public int Id { get; set; }
+
+ public int StatusId { get; set; }
+
+ public Nullable PriorityId { get; set; }
+
+ public int CreatedId { get; set; }
+
+ public string Summary { get; set; }
+
+ public string Details { get; set; }
+
+ public Nullable StartDate { get; set; }
+
+ public Nullable DueDate { get; set; }
+
+ public Nullable CompleteDate { get; set; }
+
+ public Nullable AssignedId { get; set; }
+
+ public System.DateTime CreatedDate { get; set; }
+
+ public System.DateTime ModifiedDate { get; set; }
+
+ public byte[] RowVersion { get; set; }
+
+ public string LastModifiedBy { get; set; }
+
+
+
+ public virtual ICollection Audits { get; set; }
+
+ public virtual Priority Priority { get; set; }
+
+ public virtual Status Status { get; set; }
+
+ public virtual User User { get; set; }
+
+ public virtual User User1 { get; set; }
+
+ public virtual TaskExtended TaskExtended { get; set; }
+
+}
+
}
diff --git a/Source/Samples/net40/Tracker.SqlServer.Entities/TaskExtended.cs b/Source/Samples/net40/Tracker.SqlServer.Entities/TaskExtended.cs
index 5f59f9d..4533b5f 100644
--- a/Source/Samples/net40/Tracker.SqlServer.Entities/TaskExtended.cs
+++ b/Source/Samples/net40/Tracker.SqlServer.Entities/TaskExtended.cs
@@ -1,3 +1,4 @@
+
//------------------------------------------------------------------------------
//
// This code was generated from a template.
@@ -7,20 +8,32 @@
//
//------------------------------------------------------------------------------
+
namespace Tracker.SqlServer.Entities
{
- using System;
+
+using System;
using System.Collections.Generic;
- public partial class TaskExtended
- {
- public int TaskId { get; set; }
- public string Browser { get; set; }
- public string OS { get; set; }
- public System.DateTime CreatedDate { get; set; }
- public System.DateTime ModifiedDate { get; set; }
- public byte[] RowVersion { get; set; }
-
- public virtual Task Task { get; set; }
- }
+public partial class TaskExtended
+{
+
+ public int TaskId { get; set; }
+
+ public string Browser { get; set; }
+
+ public string OS { get; set; }
+
+ public System.DateTime CreatedDate { get; set; }
+
+ public System.DateTime ModifiedDate { get; set; }
+
+ public byte[] RowVersion { get; set; }
+
+
+
+ public virtual Task Task { get; set; }
+
+}
+
}
diff --git a/Source/Samples/net40/Tracker.SqlServer.Entities/Tracker.Context.cs b/Source/Samples/net40/Tracker.SqlServer.Entities/Tracker.Context.cs
index ccf31f8..b196ef4 100644
--- a/Source/Samples/net40/Tracker.SqlServer.Entities/Tracker.Context.cs
+++ b/Source/Samples/net40/Tracker.SqlServer.Entities/Tracker.Context.cs
@@ -1,4 +1,6 @@
-//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
//
// This code was generated from a template.
//
@@ -7,30 +9,52 @@
//
//------------------------------------------------------------------------------
+
namespace Tracker.SqlServer.Entities
{
- using System;
- using System.Data.Entity;
- using System.Data.Entity.Infrastructure;
-
- public partial class TrackerEntities : DbContext
+
+using System;
+using System.Data.Entity;
+using System.Data.Entity.Infrastructure;
+
+
+public partial class TrackerEntities : DbContext
+{
+ public TrackerEntities()
+ : base("name=TrackerEntities")
{
- public TrackerEntities()
- : base("name=TrackerEntities")
- {
- }
-
- protected override void OnModelCreating(DbModelBuilder modelBuilder)
- {
- throw new UnintentionalCodeFirstException();
- }
-
- public virtual DbSet Audits { get; set; }
- public virtual DbSet Priorities { get; set; }
- public virtual DbSet Roles { get; set; }
- public virtual DbSet Status { get; set; }
- public virtual DbSet Tasks { get; set; }
- public virtual DbSet TaskExtendeds { get; set; }
- public virtual DbSet Users { get; set; }
+
+ }
+
+ protected override void OnModelCreating(DbModelBuilder modelBuilder)
+ {
+ throw new UnintentionalCodeFirstException();
}
+
+
+ public virtual DbSet Audits { get; set; }
+
+ public virtual DbSet Priorities { get; set; }
+
+ public virtual DbSet Roles { get; set; }
+
+ public virtual DbSet Status { get; set; }
+
+ public virtual DbSet Tasks { get; set; }
+
+ public virtual DbSet TaskExtendeds { get; set; }
+
+ public virtual DbSet Users { get; set; }
+
+ public virtual DbSet
- Items { get; set; }
+
+ public virtual DbSet Item_2 { get; set; }
+
+ public virtual DbSet Products { get; set; }
+
+ public virtual DbSet ProductSummaries { get; set; }
+
}
+
+}
+
diff --git a/Source/Samples/net40/Tracker.SqlServer.Entities/Tracker.Designer.cs b/Source/Samples/net40/Tracker.SqlServer.Entities/Tracker.Designer.cs
index 48f2f0b..71f238c 100644
--- a/Source/Samples/net40/Tracker.SqlServer.Entities/Tracker.Designer.cs
+++ b/Source/Samples/net40/Tracker.SqlServer.Entities/Tracker.Designer.cs
@@ -1,4 +1,4 @@
-// T4 code generation is enabled for model 'C:\Projects\github\EntityFramework.Extended\Source\Samples\net40\Tracker.SqlServer.Entities\Tracker.edmx'.
+// T4 code generation is enabled for model 'E:\Projects\EntityFramework.Extended\modif\Source\Samples\net40\Tracker.SqlServer.Entities\Tracker.edmx'.
// To enable legacy code generation, change the value of the 'Code Generation Strategy' designer
// property to 'Legacy ObjectContext'. This property is available in the Properties Window when the model
// is open in the designer.
diff --git a/Source/Samples/net40/Tracker.SqlServer.Entities/Tracker.SqlServer.Entities.net40.csproj b/Source/Samples/net40/Tracker.SqlServer.Entities/Tracker.SqlServer.Entities.net40.csproj
index b1734e5..e23ec36 100644
--- a/Source/Samples/net40/Tracker.SqlServer.Entities/Tracker.SqlServer.Entities.net40.csproj
+++ b/Source/Samples/net40/Tracker.SqlServer.Entities/Tracker.SqlServer.Entities.net40.csproj
@@ -59,9 +59,21 @@
Tracker.tt
+
+ Tracker.tt
+
+
+ Tracker.tt
+
Tracker.tt
+
+ Tracker.tt
+
+
+ Tracker.tt
+
Tracker.tt
diff --git a/Source/Samples/net40/Tracker.SqlServer.Entities/Tracker.cs b/Source/Samples/net40/Tracker.SqlServer.Entities/Tracker.cs
index 7cc0662..c36263e 100644
--- a/Source/Samples/net40/Tracker.SqlServer.Entities/Tracker.cs
+++ b/Source/Samples/net40/Tracker.SqlServer.Entities/Tracker.cs
@@ -1,4 +1,6 @@
-//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
//
// This code was generated from a template.
//
@@ -7,3 +9,4 @@
//
//------------------------------------------------------------------------------
+
diff --git a/Source/Samples/net40/Tracker.SqlServer.Entities/Tracker.edmx b/Source/Samples/net40/Tracker.SqlServer.Entities/Tracker.edmx
index b55f266..1e8559c 100644
--- a/Source/Samples/net40/Tracker.SqlServer.Entities/Tracker.edmx
+++ b/Source/Samples/net40/Tracker.SqlServer.Entities/Tracker.edmx
@@ -4,7 +4,7 @@
-
+
@@ -18,6 +18,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -30,6 +62,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -112,6 +162,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -222,13 +296,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
@@ -266,8 +352,7 @@
-
-
+
@@ -514,7 +599,97 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -635,6 +810,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Source/Samples/net40/Tracker.SqlServer.Entities/Tracker.edmx.diagram b/Source/Samples/net40/Tracker.SqlServer.Entities/Tracker.edmx.diagram
index 80b310d..d2bcfda 100644
--- a/Source/Samples/net40/Tracker.SqlServer.Entities/Tracker.edmx.diagram
+++ b/Source/Samples/net40/Tracker.SqlServer.Entities/Tracker.edmx.diagram
@@ -4,7 +4,7 @@
-
+
@@ -20,6 +20,12 @@
+
+
+
+
+
+
diff --git a/Source/Samples/net40/Tracker.SqlServer.Entities/User.cs b/Source/Samples/net40/Tracker.SqlServer.Entities/User.cs
index 725ec8d..71b871c 100644
--- a/Source/Samples/net40/Tracker.SqlServer.Entities/User.cs
+++ b/Source/Samples/net40/Tracker.SqlServer.Entities/User.cs
@@ -1,3 +1,4 @@
+
//------------------------------------------------------------------------------
//
// This code was generated from a template.
@@ -7,41 +8,72 @@
//
//------------------------------------------------------------------------------
+
namespace Tracker.SqlServer.Entities
{
- using System;
+
+using System;
using System.Collections.Generic;
- public partial class User
+public partial class User
+{
+
+ public User()
{
- public User()
- {
- this.Audits = new HashSet();
- this.Tasks = new HashSet();
- this.Tasks1 = new HashSet();
- this.Roles = new HashSet();
- }
-
- public int Id { get; set; }
- public string EmailAddress { get; set; }
- public string FirstName { get; set; }
- public string LastName { get; set; }
- public byte[] Avatar { get; set; }
- public System.DateTime CreatedDate { get; set; }
- public System.DateTime ModifiedDate { get; set; }
- public byte[] RowVersion { get; set; }
- public string PasswordHash { get; set; }
- public string PasswordSalt { get; set; }
- public string Comment { get; set; }
- public bool IsApproved { get; set; }
- public Nullable LastLoginDate { get; set; }
- public System.DateTime LastActivityDate { get; set; }
- public Nullable LastPasswordChangeDate { get; set; }
- public string AvatarType { get; set; }
-
- public virtual ICollection Audits { get; set; }
- public virtual ICollection Tasks { get; set; }
- public virtual ICollection Tasks1 { get; set; }
- public virtual ICollection Roles { get; set; }
+
+ this.Audits = new HashSet();
+
+ this.Tasks = new HashSet();
+
+ this.Tasks1 = new HashSet();
+
+ this.Roles = new HashSet();
+
}
+
+
+ public int Id { get; set; }
+
+ public string EmailAddress { get; set; }
+
+ public string FirstName { get; set; }
+
+ public string LastName { get; set; }
+
+ public byte[] Avatar { get; set; }
+
+ public System.DateTime CreatedDate { get; set; }
+
+ public System.DateTime ModifiedDate { get; set; }
+
+ public byte[] RowVersion { get; set; }
+
+ public string PasswordHash { get; set; }
+
+ public string PasswordSalt { get; set; }
+
+ public string Comment { get; set; }
+
+ public bool IsApproved { get; set; }
+
+ public Nullable LastLoginDate { get; set; }
+
+ public System.DateTime LastActivityDate { get; set; }
+
+ public Nullable LastPasswordChangeDate { get; set; }
+
+ public string AvatarType { get; set; }
+
+
+
+ public virtual ICollection Audits { get; set; }
+
+ public virtual ICollection Tasks { get; set; }
+
+ public virtual ICollection Tasks1 { get; set; }
+
+ public virtual ICollection Roles { get; set; }
+
+}
+
}
diff --git a/Source/Samples/net40/Tracker.SqlServer.Test/ExtensionTest.cs b/Source/Samples/net40/Tracker.SqlServer.Test/ExtensionTest.cs
index 11dd2d0..44be2c0 100644
--- a/Source/Samples/net40/Tracker.SqlServer.Test/ExtensionTest.cs
+++ b/Source/Samples/net40/Tracker.SqlServer.Test/ExtensionTest.cs
@@ -70,5 +70,171 @@ public void TransactionScopeObjectContext()
}
}
+
+ private void _Insert(TrackerEntities db)
+ {
+ db.Database.Log = s => System.Diagnostics.Debug.WriteLine(s);
+ db.ProductSummaries.Delete();
+ var query = from product in db.Products
+ join item2 in (
+ from item in db.Items
+ group item by item.ProductId into grItem
+ select new
+ {
+ ProductId = grItem.Key,
+ AvgPrice = grItem.Average(x => x.ListPrice + x.UnitCost)
+ }
+ ) on product.ProductId equals item2.ProductId into items
+ from item3 in items.DefaultIfEmpty()
+ select new ProductSummary2
+ {
+ ProductId = product.ProductId,
+ Name = product.Name,
+ AvgPrice = item3.AvgPrice ?? 0
+ };
+ db.ProductSummaries.Insert(query);
+ var source = query.ToArray();
+ var result = db.ProductSummaries.ToArray();
+ for (int i = 0; i < source.Length; i++)
+ {
+ source[i].AvgPrice = Math.Round(source[i].AvgPrice, 2, MidpointRounding.AwayFromZero); //In database, only two digits after decimal point
+ source[i].Verified = true; //Verified was not set in query. In database, its default value is true (1)
+ }
+ Assert.True(result.OrderBy(i => i.ProductId).SequenceEqual(source.OrderBy(i => i.ProductId), new ProductSummaryComparer()));
+
+ db.Item_2.Delete();
+ var query2 = db.Items.Where(item => item.ListPrice / item.UnitCost >= 5);
+ db.Item_2.Insert(query2);
+ var source2 = query2.ToArray().OrderBy(i => i.ItemId);
+ var result2 = db.Item_2.ToArray().Select(i => ItemComparer.GetItem(i)).OrderBy(i => i.ItemId);
+ Assert.True(result2.SequenceEqual(source2, new ItemComparer()));
+
+
+ db.Item_2.Delete();
+ var query3 = from item in db.Items where item.ProductId == "K9-RT-02" select item;
+ db.Item_2.Insert(query3);
+ var source3 = query3.ToArray().OrderBy(item => item.ItemId);
+ var result3 = db.Item_2.ToArray().Select(i => ItemComparer.GetItem(i)).OrderBy(item => item.ItemId);
+ Assert.True(result3.SequenceEqual(source3, new ItemComparer()));
+ }
+
+ [Fact]
+ public void InsertNoTransaction()
+ {
+ using (var db = new TrackerEntities())
+ {
+ _Insert(db);
+ }
+ }
+
+ [Fact]
+ public void InsertInTransaction()
+ {
+ using (var db = new TrackerEntities())
+ using (var tx = db.Database.BeginTransaction())
+ {
+ _Insert(db);
+ tx.Commit();
+ }
+ }
+
+ [Fact]
+ public void InsertInTransactionScope()
+ {
+ using (var tx = new TransactionScope())
+ using (var db = new TrackerEntities())
+ {
+ _Insert(db);
+ tx.Complete();
+ }
+ }
+ }
+
+ class ProductSummary2 : ProductSummary { }
+
+ class ProductSummaryComparer : IEqualityComparer, System.Collections.IComparer
+ {
+ public int Compare(object x, object y)
+ {
+ if (x == null && y == null) return 0;
+ var x2 = x as ProductSummary;
+ var y2 = y as ProductSummary;
+ if (x2 != null && y2 != null)
+ {
+ if (x2.ProductId == y2.ProductId
+ && x2.Name == y2.Name
+ && x2.AvgPrice == y2.AvgPrice
+ && x2.Verified == y2.Verified)
+ return 0;
+ }
+ return -1;
+ }
+
+ public bool Equals(ProductSummary x, ProductSummary y)
+ {
+ return Compare(x, y) == 0;
+ }
+
+ public int GetHashCode(ProductSummary obj)
+ {
+ if (obj == null) return 0;
+ return obj.ProductId.GetHashCode();
+ }
+ }
+
+ class ItemComparer : IEqualityComparer
- , System.Collections.IComparer
+ {
+ public int Compare(object x, object y)
+ {
+ if (x == null && y == null) return 0;
+ if (x == null || y == null) return -1;
+ Item item = GetItem(x), item2 = GetItem(y);
+ if (item.ItemId == item2.ItemId
+ && item.ProductId == item2.ProductId
+ && item.ListPrice == item2.ListPrice
+ && item.UnitCost == item2.UnitCost
+ && item.Supplier == item2.Supplier
+ && item.Status == item2.Status
+ && item.Attr1 == item2.Attr1
+ && item.Attr2 == item2.Attr2
+ && item.Attr3 == item2.Attr3
+ && item.Attr4 == item2.Attr4
+ && item.Attr5 == item2.Attr5) return 0;
+ return -1;
+ }
+
+ public bool Equals(Item x, Item y)
+ {
+ return Compare(x, y) == 0;
+ }
+
+ public int GetHashCode(Item obj)
+ {
+ return obj.ItemId.GetHashCode();
+ }
+
+ public static Item GetItem(object obj)
+ {
+ if (obj is Item) return obj as Item;
+ if (obj is Item_2)
+ {
+ var item2 = obj as Item_2;
+ return new Item
+ {
+ ItemId = item2.ItemId,
+ ProductId = item2.ProductId,
+ ListPrice = item2.ListPrice,
+ UnitCost = item2.UnitCost,
+ Supplier = item2.Supplier,
+ Status = item2.Status,
+ Attr1 = item2.Attr1,
+ Attr2 = item2.Attr2,
+ Attr3 = item2.Attr3,
+ Attr4 = item2.Attr4,
+ Attr5 = item2.Attr5
+ };
+ }
+ return null;
+ }
}
}
diff --git a/Source/Samples/net40/Tracker.SqlServer.Test/Tracker.SqlServer.Test.net40.csproj b/Source/Samples/net40/Tracker.SqlServer.Test/Tracker.SqlServer.Test.net40.csproj
index 1295e6a..944dc16 100644
--- a/Source/Samples/net40/Tracker.SqlServer.Test/Tracker.SqlServer.Test.net40.csproj
+++ b/Source/Samples/net40/Tracker.SqlServer.Test/Tracker.SqlServer.Test.net40.csproj
@@ -117,6 +117,9 @@
+
+
+
+
\ No newline at end of file
diff --git a/Source/Samples/net45/Tracker.MySql.Entities/Tracker.cs b/Source/Samples/net45/Tracker.MySql.Entities/Tracker.cs
new file mode 100644
index 0000000..7cc0662
--- /dev/null
+++ b/Source/Samples/net45/Tracker.MySql.Entities/Tracker.cs
@@ -0,0 +1,9 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated from a template.
+//
+// Manual changes to this file may cause unexpected behavior in your application.
+// Manual changes to this file will be overwritten if the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
diff --git a/Source/Samples/net45/Tracker.MySql.Entities/Tracker.edmx b/Source/Samples/net45/Tracker.MySql.Entities/Tracker.edmx
new file mode 100644
index 0000000..a85e3fd
--- /dev/null
+++ b/Source/Samples/net45/Tracker.MySql.Entities/Tracker.edmx
@@ -0,0 +1,832 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Source/Samples/net45/Tracker.MySql.Entities/Tracker.edmx.diagram b/Source/Samples/net45/Tracker.MySql.Entities/Tracker.edmx.diagram
new file mode 100644
index 0000000..41ce5d7
--- /dev/null
+++ b/Source/Samples/net45/Tracker.MySql.Entities/Tracker.edmx.diagram
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Source/Samples/net45/Tracker.MySql.Entities/Tracker.tt b/Source/Samples/net45/Tracker.MySql.Entities/Tracker.tt
new file mode 100644
index 0000000..b856ae3
--- /dev/null
+++ b/Source/Samples/net45/Tracker.MySql.Entities/Tracker.tt
@@ -0,0 +1,733 @@
+<#@ template language="C#" debug="false" hostspecific="true"#>
+<#@ include file="EF6.Utility.CS.ttinclude"#><#@
+ output extension=".cs"#><#
+
+const string inputFile = @"Tracker.edmx";
+var textTransform = DynamicTextTransformation.Create(this);
+var code = new CodeGenerationTools(this);
+var ef = new MetadataTools(this);
+var typeMapper = new TypeMapper(code, ef, textTransform.Errors);
+var fileManager = EntityFrameworkTemplateFileManager.Create(this);
+var itemCollection = new EdmMetadataLoader(textTransform.Host, textTransform.Errors).CreateEdmItemCollection(inputFile);
+var codeStringGenerator = new CodeStringGenerator(code, typeMapper, ef);
+
+if (!typeMapper.VerifyCaseInsensitiveTypeUniqueness(typeMapper.GetAllGlobalItems(itemCollection), inputFile))
+{
+ return string.Empty;
+}
+
+WriteHeader(codeStringGenerator, fileManager);
+
+foreach (var entity in typeMapper.GetItemsToGenerate(itemCollection))
+{
+ fileManager.StartNewFile(entity.Name + ".cs");
+ BeginNamespace(code);
+#>
+<#=codeStringGenerator.UsingDirectives(inHeader: false)#>
+<#=codeStringGenerator.EntityClassOpening(entity)#>
+{
+<#
+ var propertiesWithDefaultValues = typeMapper.GetPropertiesWithDefaultValues(entity);
+ var collectionNavigationProperties = typeMapper.GetCollectionNavigationProperties(entity);
+ var complexProperties = typeMapper.GetComplexProperties(entity);
+
+ if (propertiesWithDefaultValues.Any() || collectionNavigationProperties.Any() || complexProperties.Any())
+ {
+#>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
+ public <#=code.Escape(entity)#>()
+ {
+<#
+ foreach (var edmProperty in propertiesWithDefaultValues)
+ {
+#>
+ this.<#=code.Escape(edmProperty)#> = <#=typeMapper.CreateLiteral(edmProperty.DefaultValue)#>;
+<#
+ }
+
+ foreach (var navigationProperty in collectionNavigationProperties)
+ {
+#>
+ this.<#=code.Escape(navigationProperty)#> = new HashSet<<#=typeMapper.GetTypeName(navigationProperty.ToEndMember.GetEntityType())#>>();
+<#
+ }
+
+ foreach (var complexProperty in complexProperties)
+ {
+#>
+ this.<#=code.Escape(complexProperty)#> = new <#=typeMapper.GetTypeName(complexProperty.TypeUsage)#>();
+<#
+ }
+#>
+ }
+
+<#
+ }
+
+ var simpleProperties = typeMapper.GetSimpleProperties(entity);
+ if (simpleProperties.Any())
+ {
+ foreach (var edmProperty in simpleProperties)
+ {
+#>
+ <#=codeStringGenerator.Property(edmProperty)#>
+<#
+ }
+ }
+
+ if (complexProperties.Any())
+ {
+#>
+
+<#
+ foreach(var complexProperty in complexProperties)
+ {
+#>
+ <#=codeStringGenerator.Property(complexProperty)#>
+<#
+ }
+ }
+
+ var navigationProperties = typeMapper.GetNavigationProperties(entity);
+ if (navigationProperties.Any())
+ {
+#>
+
+<#
+ foreach (var navigationProperty in navigationProperties)
+ {
+ if (navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many)
+ {
+#>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
+<#
+ }
+#>
+ <#=codeStringGenerator.NavigationProperty(navigationProperty)#>
+<#
+ }
+ }
+#>
+}
+<#
+ EndNamespace(code);
+}
+
+foreach (var complex in typeMapper.GetItemsToGenerate(itemCollection))
+{
+ fileManager.StartNewFile(complex.Name + ".cs");
+ BeginNamespace(code);
+#>
+<#=codeStringGenerator.UsingDirectives(inHeader: false, includeCollections: false)#>
+<#=Accessibility.ForType(complex)#> partial class <#=code.Escape(complex)#>
+{
+<#
+ var complexProperties = typeMapper.GetComplexProperties(complex);
+ var propertiesWithDefaultValues = typeMapper.GetPropertiesWithDefaultValues(complex);
+
+ if (propertiesWithDefaultValues.Any() || complexProperties.Any())
+ {
+#>
+ public <#=code.Escape(complex)#>()
+ {
+<#
+ foreach (var edmProperty in propertiesWithDefaultValues)
+ {
+#>
+ this.<#=code.Escape(edmProperty)#> = <#=typeMapper.CreateLiteral(edmProperty.DefaultValue)#>;
+<#
+ }
+
+ foreach (var complexProperty in complexProperties)
+ {
+#>
+ this.<#=code.Escape(complexProperty)#> = new <#=typeMapper.GetTypeName(complexProperty.TypeUsage)#>();
+<#
+ }
+#>
+ }
+
+<#
+ }
+
+ var simpleProperties = typeMapper.GetSimpleProperties(complex);
+ if (simpleProperties.Any())
+ {
+ foreach(var edmProperty in simpleProperties)
+ {
+#>
+ <#=codeStringGenerator.Property(edmProperty)#>
+<#
+ }
+ }
+
+ if (complexProperties.Any())
+ {
+#>
+
+<#
+ foreach(var edmProperty in complexProperties)
+ {
+#>
+ <#=codeStringGenerator.Property(edmProperty)#>
+<#
+ }
+ }
+#>
+}
+<#
+ EndNamespace(code);
+}
+
+foreach (var enumType in typeMapper.GetEnumItemsToGenerate(itemCollection))
+{
+ fileManager.StartNewFile(enumType.Name + ".cs");
+ BeginNamespace(code);
+#>
+<#=codeStringGenerator.UsingDirectives(inHeader: false, includeCollections: false)#>
+<#
+ if (typeMapper.EnumIsFlags(enumType))
+ {
+#>
+[Flags]
+<#
+ }
+#>
+<#=codeStringGenerator.EnumOpening(enumType)#>
+{
+<#
+ var foundOne = false;
+
+ foreach (MetadataItem member in typeMapper.GetEnumMembers(enumType))
+ {
+ foundOne = true;
+#>
+ <#=code.Escape(typeMapper.GetEnumMemberName(member))#> = <#=typeMapper.GetEnumMemberValue(member)#>,
+<#
+ }
+
+ if (foundOne)
+ {
+ this.GenerationEnvironment.Remove(this.GenerationEnvironment.Length - 3, 1);
+ }
+#>
+}
+<#
+ EndNamespace(code);
+}
+
+fileManager.Process();
+
+#>
+<#+
+
+public void WriteHeader(CodeStringGenerator codeStringGenerator, EntityFrameworkTemplateFileManager fileManager)
+{
+ fileManager.StartHeader();
+#>
+//------------------------------------------------------------------------------
+//
+// <#=CodeGenerationTools.GetResourceString("Template_GeneratedCodeCommentLine1")#>
+//
+// <#=CodeGenerationTools.GetResourceString("Template_GeneratedCodeCommentLine2")#>
+// <#=CodeGenerationTools.GetResourceString("Template_GeneratedCodeCommentLine3")#>
+//
+//------------------------------------------------------------------------------
+<#=codeStringGenerator.UsingDirectives(inHeader: true)#>
+<#+
+ fileManager.EndBlock();
+}
+
+public void BeginNamespace(CodeGenerationTools code)
+{
+ var codeNamespace = code.VsNamespaceSuggestion();
+ if (!String.IsNullOrEmpty(codeNamespace))
+ {
+#>
+namespace <#=code.EscapeNamespace(codeNamespace)#>
+{
+<#+
+ PushIndent(" ");
+ }
+}
+
+public void EndNamespace(CodeGenerationTools code)
+{
+ if (!String.IsNullOrEmpty(code.VsNamespaceSuggestion()))
+ {
+ PopIndent();
+#>
+}
+<#+
+ }
+}
+
+public const string TemplateId = "CSharp_DbContext_Types_EF6";
+
+public class CodeStringGenerator
+{
+ private readonly CodeGenerationTools _code;
+ private readonly TypeMapper _typeMapper;
+ private readonly MetadataTools _ef;
+
+ public CodeStringGenerator(CodeGenerationTools code, TypeMapper typeMapper, MetadataTools ef)
+ {
+ ArgumentNotNull(code, "code");
+ ArgumentNotNull(typeMapper, "typeMapper");
+ ArgumentNotNull(ef, "ef");
+
+ _code = code;
+ _typeMapper = typeMapper;
+ _ef = ef;
+ }
+
+ public string Property(EdmProperty edmProperty)
+ {
+ return string.Format(
+ CultureInfo.InvariantCulture,
+ "{0} {1} {2} {{ {3}get; {4}set; }}",
+ Accessibility.ForProperty(edmProperty),
+ _typeMapper.GetTypeName(edmProperty.TypeUsage),
+ _code.Escape(edmProperty),
+ _code.SpaceAfter(Accessibility.ForGetter(edmProperty)),
+ _code.SpaceAfter(Accessibility.ForSetter(edmProperty)));
+ }
+
+ public string NavigationProperty(NavigationProperty navProp)
+ {
+ var endType = _typeMapper.GetTypeName(navProp.ToEndMember.GetEntityType());
+ return string.Format(
+ CultureInfo.InvariantCulture,
+ "{0} {1} {2} {{ {3}get; {4}set; }}",
+ AccessibilityAndVirtual(Accessibility.ForNavigationProperty(navProp)),
+ navProp.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ? ("ICollection<" + endType + ">") : endType,
+ _code.Escape(navProp),
+ _code.SpaceAfter(Accessibility.ForGetter(navProp)),
+ _code.SpaceAfter(Accessibility.ForSetter(navProp)));
+ }
+
+ public string AccessibilityAndVirtual(string accessibility)
+ {
+ return accessibility + (accessibility != "private" ? " virtual" : "");
+ }
+
+ public string EntityClassOpening(EntityType entity)
+ {
+ return string.Format(
+ CultureInfo.InvariantCulture,
+ "{0} {1}partial class {2}{3}",
+ Accessibility.ForType(entity),
+ _code.SpaceAfter(_code.AbstractOption(entity)),
+ _code.Escape(entity),
+ _code.StringBefore(" : ", _typeMapper.GetTypeName(entity.BaseType)));
+ }
+
+ public string EnumOpening(SimpleType enumType)
+ {
+ return string.Format(
+ CultureInfo.InvariantCulture,
+ "{0} enum {1} : {2}",
+ Accessibility.ForType(enumType),
+ _code.Escape(enumType),
+ _code.Escape(_typeMapper.UnderlyingClrType(enumType)));
+ }
+
+ public void WriteFunctionParameters(EdmFunction edmFunction, Action writeParameter)
+ {
+ var parameters = FunctionImportParameter.Create(edmFunction.Parameters, _code, _ef);
+ foreach (var parameter in parameters.Where(p => p.NeedsLocalVariable))
+ {
+ var isNotNull = parameter.IsNullableOfT ? parameter.FunctionParameterName + ".HasValue" : parameter.FunctionParameterName + " != null";
+ var notNullInit = "new ObjectParameter(\"" + parameter.EsqlParameterName + "\", " + parameter.FunctionParameterName + ")";
+ var nullInit = "new ObjectParameter(\"" + parameter.EsqlParameterName + "\", typeof(" + TypeMapper.FixNamespaces(parameter.RawClrTypeName) + "))";
+ writeParameter(parameter.LocalVariableName, isNotNull, notNullInit, nullInit);
+ }
+ }
+
+ public string ComposableFunctionMethod(EdmFunction edmFunction, string modelNamespace)
+ {
+ var parameters = _typeMapper.GetParameters(edmFunction);
+
+ return string.Format(
+ CultureInfo.InvariantCulture,
+ "{0} IQueryable<{1}> {2}({3})",
+ AccessibilityAndVirtual(Accessibility.ForMethod(edmFunction)),
+ _typeMapper.GetTypeName(_typeMapper.GetReturnType(edmFunction), modelNamespace),
+ _code.Escape(edmFunction),
+ string.Join(", ", parameters.Select(p => TypeMapper.FixNamespaces(p.FunctionParameterType) + " " + p.FunctionParameterName).ToArray()));
+ }
+
+ public string ComposableCreateQuery(EdmFunction edmFunction, string modelNamespace)
+ {
+ var parameters = _typeMapper.GetParameters(edmFunction);
+
+ return string.Format(
+ CultureInfo.InvariantCulture,
+ "return ((IObjectContextAdapter)this).ObjectContext.CreateQuery<{0}>(\"[{1}].[{2}]({3})\"{4});",
+ _typeMapper.GetTypeName(_typeMapper.GetReturnType(edmFunction), modelNamespace),
+ edmFunction.NamespaceName,
+ edmFunction.Name,
+ string.Join(", ", parameters.Select(p => "@" + p.EsqlParameterName).ToArray()),
+ _code.StringBefore(", ", string.Join(", ", parameters.Select(p => p.ExecuteParameterName).ToArray())));
+ }
+
+ public string FunctionMethod(EdmFunction edmFunction, string modelNamespace, bool includeMergeOption)
+ {
+ var parameters = _typeMapper.GetParameters(edmFunction);
+ var returnType = _typeMapper.GetReturnType(edmFunction);
+
+ var paramList = String.Join(", ", parameters.Select(p => TypeMapper.FixNamespaces(p.FunctionParameterType) + " " + p.FunctionParameterName).ToArray());
+ if (includeMergeOption)
+ {
+ paramList = _code.StringAfter(paramList, ", ") + "MergeOption mergeOption";
+ }
+
+ return string.Format(
+ CultureInfo.InvariantCulture,
+ "{0} {1} {2}({3})",
+ AccessibilityAndVirtual(Accessibility.ForMethod(edmFunction)),
+ returnType == null ? "int" : "ObjectResult<" + _typeMapper.GetTypeName(returnType, modelNamespace) + ">",
+ _code.Escape(edmFunction),
+ paramList);
+ }
+
+ public string ExecuteFunction(EdmFunction edmFunction, string modelNamespace, bool includeMergeOption)
+ {
+ var parameters = _typeMapper.GetParameters(edmFunction);
+ var returnType = _typeMapper.GetReturnType(edmFunction);
+
+ var callParams = _code.StringBefore(", ", String.Join(", ", parameters.Select(p => p.ExecuteParameterName).ToArray()));
+ if (includeMergeOption)
+ {
+ callParams = ", mergeOption" + callParams;
+ }
+
+ return string.Format(
+ CultureInfo.InvariantCulture,
+ "return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction{0}(\"{1}\"{2});",
+ returnType == null ? "" : "<" + _typeMapper.GetTypeName(returnType, modelNamespace) + ">",
+ edmFunction.Name,
+ callParams);
+ }
+
+ public string DbSet(EntitySet entitySet)
+ {
+ return string.Format(
+ CultureInfo.InvariantCulture,
+ "{0} virtual DbSet<{1}> {2} {{ get; set; }}",
+ Accessibility.ForReadOnlyProperty(entitySet),
+ _typeMapper.GetTypeName(entitySet.ElementType),
+ _code.Escape(entitySet));
+ }
+
+ public string UsingDirectives(bool inHeader, bool includeCollections = true)
+ {
+ return inHeader == string.IsNullOrEmpty(_code.VsNamespaceSuggestion())
+ ? string.Format(
+ CultureInfo.InvariantCulture,
+ "{0}using System;{1}" +
+ "{2}",
+ inHeader ? Environment.NewLine : "",
+ includeCollections ? (Environment.NewLine + "using System.Collections.Generic;") : "",
+ inHeader ? "" : Environment.NewLine)
+ : "";
+ }
+}
+
+public class TypeMapper
+{
+ private const string ExternalTypeNameAttributeName = @"http://schemas.microsoft.com/ado/2006/04/codegeneration:ExternalTypeName";
+
+ private readonly System.Collections.IList _errors;
+ private readonly CodeGenerationTools _code;
+ private readonly MetadataTools _ef;
+
+ public TypeMapper(CodeGenerationTools code, MetadataTools ef, System.Collections.IList errors)
+ {
+ ArgumentNotNull(code, "code");
+ ArgumentNotNull(ef, "ef");
+ ArgumentNotNull(errors, "errors");
+
+ _code = code;
+ _ef = ef;
+ _errors = errors;
+ }
+
+ public static string FixNamespaces(string typeName)
+ {
+ return typeName.Replace("System.Data.Spatial.", "System.Data.Entity.Spatial.");
+ }
+
+ public string GetTypeName(TypeUsage typeUsage)
+ {
+ return typeUsage == null ? null : GetTypeName(typeUsage.EdmType, _ef.IsNullable(typeUsage), modelNamespace: null);
+ }
+
+ public string GetTypeName(EdmType edmType)
+ {
+ return GetTypeName(edmType, isNullable: null, modelNamespace: null);
+ }
+
+ public string GetTypeName(TypeUsage typeUsage, string modelNamespace)
+ {
+ return typeUsage == null ? null : GetTypeName(typeUsage.EdmType, _ef.IsNullable(typeUsage), modelNamespace);
+ }
+
+ public string GetTypeName(EdmType edmType, string modelNamespace)
+ {
+ return GetTypeName(edmType, isNullable: null, modelNamespace: modelNamespace);
+ }
+
+ public string GetTypeName(EdmType edmType, bool? isNullable, string modelNamespace)
+ {
+ if (edmType == null)
+ {
+ return null;
+ }
+
+ var collectionType = edmType as CollectionType;
+ if (collectionType != null)
+ {
+ return String.Format(CultureInfo.InvariantCulture, "ICollection<{0}>", GetTypeName(collectionType.TypeUsage, modelNamespace));
+ }
+
+ var typeName = _code.Escape(edmType.MetadataProperties
+ .Where(p => p.Name == ExternalTypeNameAttributeName)
+ .Select(p => (string)p.Value)
+ .FirstOrDefault())
+ ?? (modelNamespace != null && edmType.NamespaceName != modelNamespace ?
+ _code.CreateFullName(_code.EscapeNamespace(edmType.NamespaceName), _code.Escape(edmType)) :
+ _code.Escape(edmType));
+
+ if (edmType is StructuralType)
+ {
+ return typeName;
+ }
+
+ if (edmType is SimpleType)
+ {
+ var clrType = UnderlyingClrType(edmType);
+ if (!IsEnumType(edmType))
+ {
+ typeName = _code.Escape(clrType);
+ }
+
+ typeName = FixNamespaces(typeName);
+
+ return clrType.IsValueType && isNullable == true ?
+ String.Format(CultureInfo.InvariantCulture, "Nullable<{0}>", typeName) :
+ typeName;
+ }
+
+ throw new ArgumentException("edmType");
+ }
+
+ public Type UnderlyingClrType(EdmType edmType)
+ {
+ ArgumentNotNull(edmType, "edmType");
+
+ var primitiveType = edmType as PrimitiveType;
+ if (primitiveType != null)
+ {
+ return primitiveType.ClrEquivalentType;
+ }
+
+ if (IsEnumType(edmType))
+ {
+ return GetEnumUnderlyingType(edmType).ClrEquivalentType;
+ }
+
+ return typeof(object);
+ }
+
+ public object GetEnumMemberValue(MetadataItem enumMember)
+ {
+ ArgumentNotNull(enumMember, "enumMember");
+
+ var valueProperty = enumMember.GetType().GetProperty("Value");
+ return valueProperty == null ? null : valueProperty.GetValue(enumMember, null);
+ }
+
+ public string GetEnumMemberName(MetadataItem enumMember)
+ {
+ ArgumentNotNull(enumMember, "enumMember");
+
+ var nameProperty = enumMember.GetType().GetProperty("Name");
+ return nameProperty == null ? null : (string)nameProperty.GetValue(enumMember, null);
+ }
+
+ public System.Collections.IEnumerable GetEnumMembers(EdmType enumType)
+ {
+ ArgumentNotNull(enumType, "enumType");
+
+ var membersProperty = enumType.GetType().GetProperty("Members");
+ return membersProperty != null
+ ? (System.Collections.IEnumerable)membersProperty.GetValue(enumType, null)
+ : Enumerable.Empty();
+ }
+
+ public bool EnumIsFlags(EdmType enumType)
+ {
+ ArgumentNotNull(enumType, "enumType");
+
+ var isFlagsProperty = enumType.GetType().GetProperty("IsFlags");
+ return isFlagsProperty != null && (bool)isFlagsProperty.GetValue(enumType, null);
+ }
+
+ public bool IsEnumType(GlobalItem edmType)
+ {
+ ArgumentNotNull(edmType, "edmType");
+
+ return edmType.GetType().Name == "EnumType";
+ }
+
+ public PrimitiveType GetEnumUnderlyingType(EdmType enumType)
+ {
+ ArgumentNotNull(enumType, "enumType");
+
+ return (PrimitiveType)enumType.GetType().GetProperty("UnderlyingType").GetValue(enumType, null);
+ }
+
+ public string CreateLiteral(object value)
+ {
+ if (value == null || value.GetType() != typeof(TimeSpan))
+ {
+ return _code.CreateLiteral(value);
+ }
+
+ return string.Format(CultureInfo.InvariantCulture, "new TimeSpan({0})", ((TimeSpan)value).Ticks);
+ }
+
+ public bool VerifyCaseInsensitiveTypeUniqueness(IEnumerable types, string sourceFile)
+ {
+ ArgumentNotNull(types, "types");
+ ArgumentNotNull(sourceFile, "sourceFile");
+
+ var hash = new HashSet(StringComparer.InvariantCultureIgnoreCase);
+ if (types.Any(item => !hash.Add(item)))
+ {
+ _errors.Add(
+ new CompilerError(sourceFile, -1, -1, "6023",
+ String.Format(CultureInfo.CurrentCulture, CodeGenerationTools.GetResourceString("Template_CaseInsensitiveTypeConflict"))));
+ return false;
+ }
+ return true;
+ }
+
+ public IEnumerable GetEnumItemsToGenerate(IEnumerable itemCollection)
+ {
+ return GetItemsToGenerate(itemCollection)
+ .Where(e => IsEnumType(e));
+ }
+
+ public IEnumerable GetItemsToGenerate(IEnumerable itemCollection) where T: EdmType
+ {
+ return itemCollection
+ .OfType()
+ .Where(i => !i.MetadataProperties.Any(p => p.Name == ExternalTypeNameAttributeName))
+ .OrderBy(i => i.Name);
+ }
+
+ public IEnumerable GetAllGlobalItems(IEnumerable itemCollection)
+ {
+ return itemCollection
+ .Where(i => i is EntityType || i is ComplexType || i is EntityContainer || IsEnumType(i))
+ .Select(g => GetGlobalItemName(g));
+ }
+
+ public string GetGlobalItemName(GlobalItem item)
+ {
+ if (item is EdmType)
+ {
+ return ((EdmType)item).Name;
+ }
+ else
+ {
+ return ((EntityContainer)item).Name;
+ }
+ }
+
+ public IEnumerable GetSimpleProperties(EntityType type)
+ {
+ return type.Properties.Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == type);
+ }
+
+ public IEnumerable GetSimpleProperties(ComplexType type)
+ {
+ return type.Properties.Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == type);
+ }
+
+ public IEnumerable GetComplexProperties(EntityType type)
+ {
+ return type.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == type);
+ }
+
+ public IEnumerable GetComplexProperties(ComplexType type)
+ {
+ return type.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == type);
+ }
+
+ public IEnumerable GetPropertiesWithDefaultValues(EntityType type)
+ {
+ return type.Properties.Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == type && p.DefaultValue != null);
+ }
+
+ public IEnumerable GetPropertiesWithDefaultValues(ComplexType type)
+ {
+ return type.Properties.Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == type && p.DefaultValue != null);
+ }
+
+ public IEnumerable GetNavigationProperties(EntityType type)
+ {
+ return type.NavigationProperties.Where(np => np.DeclaringType == type);
+ }
+
+ public IEnumerable GetCollectionNavigationProperties(EntityType type)
+ {
+ return type.NavigationProperties.Where(np => np.DeclaringType == type && np.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many);
+ }
+
+ public FunctionParameter GetReturnParameter(EdmFunction edmFunction)
+ {
+ ArgumentNotNull(edmFunction, "edmFunction");
+
+ var returnParamsProperty = edmFunction.GetType().GetProperty("ReturnParameters");
+ return returnParamsProperty == null
+ ? edmFunction.ReturnParameter
+ : ((IEnumerable)returnParamsProperty.GetValue(edmFunction, null)).FirstOrDefault();
+ }
+
+ public bool IsComposable(EdmFunction edmFunction)
+ {
+ ArgumentNotNull(edmFunction, "edmFunction");
+
+ var isComposableProperty = edmFunction.GetType().GetProperty("IsComposableAttribute");
+ return isComposableProperty != null && (bool)isComposableProperty.GetValue(edmFunction, null);
+ }
+
+ public IEnumerable GetParameters(EdmFunction edmFunction)
+ {
+ return FunctionImportParameter.Create(edmFunction.Parameters, _code, _ef);
+ }
+
+ public TypeUsage GetReturnType(EdmFunction edmFunction)
+ {
+ var returnParam = GetReturnParameter(edmFunction);
+ return returnParam == null ? null : _ef.GetElementType(returnParam.TypeUsage);
+ }
+
+ public bool GenerateMergeOptionFunction(EdmFunction edmFunction, bool includeMergeOption)
+ {
+ var returnType = GetReturnType(edmFunction);
+ return !includeMergeOption && returnType != null && returnType.EdmType.BuiltInTypeKind == BuiltInTypeKind.EntityType;
+ }
+}
+
+public static void ArgumentNotNull(T arg, string name) where T : class
+{
+ if (arg == null)
+ {
+ throw new ArgumentNullException(name);
+ }
+}
+#>
\ No newline at end of file
diff --git a/Source/Samples/net45/Tracker.MySql.Entities/app.config b/Source/Samples/net45/Tracker.MySql.Entities/app.config
new file mode 100644
index 0000000..255c75b
--- /dev/null
+++ b/Source/Samples/net45/Tracker.MySql.Entities/app.config
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Source/Samples/net45/Tracker.MySql.Entities/audit.cs b/Source/Samples/net45/Tracker.MySql.Entities/audit.cs
new file mode 100644
index 0000000..754ead6
--- /dev/null
+++ b/Source/Samples/net45/Tracker.MySql.Entities/audit.cs
@@ -0,0 +1,29 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated from a template.
+//
+// Manual changes to this file may cause unexpected behavior in your application.
+// Manual changes to this file will be overwritten if the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace Tracker.MySql.Entities
+{
+ using System;
+ using System.Collections.Generic;
+
+ public partial class audit
+ {
+ public int Id { get; set; }
+ public System.DateTime Date { get; set; }
+ public Nullable UserId { get; set; }
+ public Nullable TaskId { get; set; }
+ public string Content { get; set; }
+ public string Username { get; set; }
+ public System.DateTime CreatedDate { get; set; }
+ public byte[] RowVersion { get; set; }
+
+ public virtual task task { get; set; }
+ public virtual user user { get; set; }
+ }
+}
diff --git a/Source/Samples/net45/Tracker.MySql.Entities/item.cs b/Source/Samples/net45/Tracker.MySql.Entities/item.cs
new file mode 100644
index 0000000..db0847c
--- /dev/null
+++ b/Source/Samples/net45/Tracker.MySql.Entities/item.cs
@@ -0,0 +1,31 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated from a template.
+//
+// Manual changes to this file may cause unexpected behavior in your application.
+// Manual changes to this file will be overwritten if the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace Tracker.MySql.Entities
+{
+ using System;
+ using System.Collections.Generic;
+
+ public partial class item
+ {
+ public string ItemId { get; set; }
+ public string ProductId { get; set; }
+ public Nullable ListPrice { get; set; }
+ public Nullable UnitCost { get; set; }
+ public Nullable Supplier { get; set; }
+ public string Status { get; set; }
+ public string Attr1 { get; set; }
+ public string Attr2 { get; set; }
+ public string Attr3 { get; set; }
+ public string Attr4 { get; set; }
+ public string Attr5 { get; set; }
+
+ public virtual product product { get; set; }
+ }
+}
diff --git a/Source/Samples/net45/Tracker.MySql.Entities/item_2.cs b/Source/Samples/net45/Tracker.MySql.Entities/item_2.cs
new file mode 100644
index 0000000..dc42fdb
--- /dev/null
+++ b/Source/Samples/net45/Tracker.MySql.Entities/item_2.cs
@@ -0,0 +1,31 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated from a template.
+//
+// Manual changes to this file may cause unexpected behavior in your application.
+// Manual changes to this file will be overwritten if the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace Tracker.MySql.Entities
+{
+ using System;
+ using System.Collections.Generic;
+
+ public partial class item_2
+ {
+ public string ItemId { get; set; }
+ public string ProductId { get; set; }
+ public Nullable ListPrice { get; set; }
+ public Nullable UnitCost { get; set; }
+ public Nullable Supplier { get; set; }
+ public string Status { get; set; }
+ public string Attr1 { get; set; }
+ public string Attr2 { get; set; }
+ public string Attr3 { get; set; }
+ public string Attr4 { get; set; }
+ public string Attr5 { get; set; }
+
+ public virtual product product { get; set; }
+ }
+}
diff --git a/Source/Samples/net45/Tracker.MySql.Entities/packages.config b/Source/Samples/net45/Tracker.MySql.Entities/packages.config
new file mode 100644
index 0000000..b3b1903
--- /dev/null
+++ b/Source/Samples/net45/Tracker.MySql.Entities/packages.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Source/Samples/net45/Tracker.MySql.Entities/priority.cs b/Source/Samples/net45/Tracker.MySql.Entities/priority.cs
new file mode 100644
index 0000000..815797a
--- /dev/null
+++ b/Source/Samples/net45/Tracker.MySql.Entities/priority.cs
@@ -0,0 +1,34 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated from a template.
+//
+// Manual changes to this file may cause unexpected behavior in your application.
+// Manual changes to this file will be overwritten if the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace Tracker.MySql.Entities
+{
+ using System;
+ using System.Collections.Generic;
+
+ public partial class priority
+ {
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
+ public priority()
+ {
+ this.tasks = new HashSet();
+ }
+
+ public int Id { get; set; }
+ public string Name { get; set; }
+ public int Order { get; set; }
+ public string Description { get; set; }
+ public System.DateTime CreatedDate { get; set; }
+ public System.DateTime ModifiedDate { get; set; }
+ public byte[] RowVersion { get; set; }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
+ public virtual ICollection tasks { get; set; }
+ }
+}
diff --git a/Source/Samples/net45/Tracker.MySql.Entities/product.cs b/Source/Samples/net45/Tracker.MySql.Entities/product.cs
new file mode 100644
index 0000000..54d674d
--- /dev/null
+++ b/Source/Samples/net45/Tracker.MySql.Entities/product.cs
@@ -0,0 +1,34 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated from a template.
+//
+// Manual changes to this file may cause unexpected behavior in your application.
+// Manual changes to this file will be overwritten if the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace Tracker.MySql.Entities
+{
+ using System;
+ using System.Collections.Generic;
+
+ public partial class product
+ {
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
+ public product()
+ {
+ this.items = new HashSet- ();
+ this.item_2 = new HashSet();
+ }
+
+ public string ProductId { get; set; }
+ public string Category { get; set; }
+ public string Name { get; set; }
+ public string Descn { get; set; }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
+ public virtual ICollection
- items { get; set; }
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
+ public virtual ICollection item_2 { get; set; }
+ }
+}
diff --git a/Source/Samples/net45/Tracker.MySql.Entities/productsummary.cs b/Source/Samples/net45/Tracker.MySql.Entities/productsummary.cs
new file mode 100644
index 0000000..ac8f8e2
--- /dev/null
+++ b/Source/Samples/net45/Tracker.MySql.Entities/productsummary.cs
@@ -0,0 +1,22 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated from a template.
+//
+// Manual changes to this file may cause unexpected behavior in your application.
+// Manual changes to this file will be overwritten if the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace Tracker.MySql.Entities
+{
+ using System;
+ using System.Collections.Generic;
+
+ public partial class productsummary
+ {
+ public string ProductId { get; set; }
+ public string Name { get; set; }
+ public decimal AvgPrice { get; set; }
+ public bool Verified { get; set; }
+ }
+}
diff --git a/Source/Samples/net45/Tracker.MySql.Entities/role.cs b/Source/Samples/net45/Tracker.MySql.Entities/role.cs
new file mode 100644
index 0000000..62f638d
--- /dev/null
+++ b/Source/Samples/net45/Tracker.MySql.Entities/role.cs
@@ -0,0 +1,24 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated from a template.
+//
+// Manual changes to this file may cause unexpected behavior in your application.
+// Manual changes to this file will be overwritten if the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace Tracker.MySql.Entities
+{
+ using System;
+ using System.Collections.Generic;
+
+ public partial class role
+ {
+ public int Id { get; set; }
+ public string Name { get; set; }
+ public string Description { get; set; }
+ public System.DateTime CreatedDate { get; set; }
+ public System.DateTime ModifiedDate { get; set; }
+ public byte[] RowVersion { get; set; }
+ }
+}
diff --git a/Source/Samples/net45/Tracker.MySql.Entities/status.cs b/Source/Samples/net45/Tracker.MySql.Entities/status.cs
new file mode 100644
index 0000000..a261c4d
--- /dev/null
+++ b/Source/Samples/net45/Tracker.MySql.Entities/status.cs
@@ -0,0 +1,34 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated from a template.
+//
+// Manual changes to this file may cause unexpected behavior in your application.
+// Manual changes to this file will be overwritten if the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace Tracker.MySql.Entities
+{
+ using System;
+ using System.Collections.Generic;
+
+ public partial class status
+ {
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
+ public status()
+ {
+ this.tasks = new HashSet();
+ }
+
+ public int Id { get; set; }
+ public string Name { get; set; }
+ public string Description { get; set; }
+ public int Order { get; set; }
+ public System.DateTime CreatedDate { get; set; }
+ public System.DateTime ModifiedDate { get; set; }
+ public byte[] RowVersion { get; set; }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
+ public virtual ICollection tasks { get; set; }
+ }
+}
diff --git a/Source/Samples/net45/Tracker.MySql.Entities/task.cs b/Source/Samples/net45/Tracker.MySql.Entities/task.cs
new file mode 100644
index 0000000..dfd000e
--- /dev/null
+++ b/Source/Samples/net45/Tracker.MySql.Entities/task.cs
@@ -0,0 +1,46 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated from a template.
+//
+// Manual changes to this file may cause unexpected behavior in your application.
+// Manual changes to this file will be overwritten if the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace Tracker.MySql.Entities
+{
+ using System;
+ using System.Collections.Generic;
+
+ public partial class task
+ {
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
+ public task()
+ {
+ this.audits = new HashSet();
+ }
+
+ public int Id { get; set; }
+ public int StatusId { get; set; }
+ public Nullable PriorityId { get; set; }
+ public int CreatedId { get; set; }
+ public string Summary { get; set; }
+ public string Details { get; set; }
+ public Nullable StartDate { get; set; }
+ public Nullable DueDate { get; set; }
+ public Nullable CompleteDate { get; set; }
+ public Nullable AssignedId { get; set; }
+ public System.DateTime CreatedDate { get; set; }
+ public System.DateTime ModifiedDate { get; set; }
+ public byte[] RowVersion { get; set; }
+ public string LastModifiedBy { get; set; }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
+ public virtual ICollection audits { get; set; }
+ public virtual priority priority { get; set; }
+ public virtual status status { get; set; }
+ public virtual user user { get; set; }
+ public virtual user user1 { get; set; }
+ public virtual taskextended taskextended { get; set; }
+ }
+}
diff --git a/Source/Samples/net45/Tracker.MySql.Entities/taskextended.cs b/Source/Samples/net45/Tracker.MySql.Entities/taskextended.cs
new file mode 100644
index 0000000..6129387
--- /dev/null
+++ b/Source/Samples/net45/Tracker.MySql.Entities/taskextended.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated from a template.
+//
+// Manual changes to this file may cause unexpected behavior in your application.
+// Manual changes to this file will be overwritten if the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace Tracker.MySql.Entities
+{
+ using System;
+ using System.Collections.Generic;
+
+ public partial class taskextended
+ {
+ public int TaskId { get; set; }
+ public string Browser { get; set; }
+ public string OS { get; set; }
+ public System.DateTime CreatedDate { get; set; }
+ public System.DateTime ModifiedDate { get; set; }
+ public byte[] RowVersion { get; set; }
+
+ public virtual task task { get; set; }
+ }
+}
diff --git a/Source/Samples/net45/Tracker.MySql.Entities/user.cs b/Source/Samples/net45/Tracker.MySql.Entities/user.cs
new file mode 100644
index 0000000..e0b6e63
--- /dev/null
+++ b/Source/Samples/net45/Tracker.MySql.Entities/user.cs
@@ -0,0 +1,49 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated from a template.
+//
+// Manual changes to this file may cause unexpected behavior in your application.
+// Manual changes to this file will be overwritten if the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace Tracker.MySql.Entities
+{
+ using System;
+ using System.Collections.Generic;
+
+ public partial class user
+ {
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
+ public user()
+ {
+ this.audits = new HashSet();
+ this.tasks = new HashSet();
+ this.tasks1 = new HashSet();
+ }
+
+ public int Id { get; set; }
+ public string EmailAddress { get; set; }
+ public string FirstName { get; set; }
+ public string LastName { get; set; }
+ public byte[] Avatar { get; set; }
+ public System.DateTime CreatedDate { get; set; }
+ public System.DateTime ModifiedDate { get; set; }
+ public byte[] RowVersion { get; set; }
+ public string PasswordHash { get; set; }
+ public string PasswordSalt { get; set; }
+ public string Comment { get; set; }
+ public bool IsApproved { get; set; }
+ public Nullable LastLoginDate { get; set; }
+ public System.DateTime LastActivityDate { get; set; }
+ public Nullable LastPasswordChangeDate { get; set; }
+ public string AvatarType { get; set; }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
+ public virtual ICollection audits { get; set; }
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
+ public virtual ICollection tasks { get; set; }
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
+ public virtual ICollection tasks1 { get; set; }
+ }
+}
diff --git a/Source/Samples/net45/Tracker.MySql.Test/App.config b/Source/Samples/net45/Tracker.MySql.Test/App.config
new file mode 100644
index 0000000..45e8c4d
--- /dev/null
+++ b/Source/Samples/net45/Tracker.MySql.Test/App.config
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Source/Samples/net45/Tracker.MySql.Test/ExtensionTest.cs b/Source/Samples/net45/Tracker.MySql.Test/ExtensionTest.cs
new file mode 100644
index 0000000..06bc028
--- /dev/null
+++ b/Source/Samples/net45/Tracker.MySql.Test/ExtensionTest.cs
@@ -0,0 +1,281 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using EntityFramework.Extensions;
+using Xunit;
+using Tracker.MySql.Entities;
+using EntityFramework;
+using EntityFramework.Batch;
+
+namespace Tracker.MySql.Test
+{
+ public class ExtensionTest
+ {
+ [Fact]
+ public void BeginTransactionObjectContext()
+ {
+ Locator.Current.Register(() => new MySqlBatchRunner());
+ try
+ {
+ using (var db = new TrackerEntities())
+ using (var tx = db.Database.BeginTransaction())
+ {
+ db.Database.Log = s => System.Diagnostics.Trace.WriteLine(s);
+ string emailDomain = "@test.com";
+
+ int count = db.users
+ .Where(u => u.EmailAddress.EndsWith(emailDomain))
+ .Update(u => new user { IsApproved = false, LastActivityDate = DateTime.Now });
+
+ count = db.users
+ .Where(u => u.EmailAddress.EndsWith(emailDomain))
+ .Delete();
+
+ tx.Commit();
+ }
+ }
+ finally
+ {
+ Locator.Current.Register(() => new SqlServerBatchRunner());
+ }
+ }
+
+ [Fact]
+ public void NoTransactionObjectContext()
+ {
+ Locator.Current.Register(() => new MySqlBatchRunner());
+ try
+ {
+ using (var db = new TrackerEntities())
+ {
+ db.Database.Log = s => System.Diagnostics.Trace.WriteLine(s);
+ string emailDomain = "@test.com";
+
+ int count = db.users
+ .Where(u => u.EmailAddress.EndsWith(emailDomain))
+ .Update(u => new user { IsApproved = false, LastActivityDate = DateTime.Now });
+
+ count = db.users
+ .Where(u => u.EmailAddress.EndsWith(emailDomain))
+ .Delete();
+
+ }
+ }
+ finally
+ {
+ Locator.Current.Register(() => new SqlServerBatchRunner());
+ }
+ }
+
+ /*** MySQL seems not to support TransactionScope ***/
+ //[Fact]
+ //public void TransactionScopeObjectContext()
+ //{
+ // using (var tx = new TransactionScope())
+ // using (var db = new TrackerEntities())
+ // {
+ // string emailDomain = "@test.com";
+
+ // int count = db.users
+ // .Where(u => u.EmailAddress.EndsWith(emailDomain))
+ // .Update(u => new user { IsApproved = false, LastActivityDate = DateTime.Now });
+
+ // count = db.users
+ // .Where(u => u.EmailAddress.EndsWith(emailDomain))
+ // .Delete();
+
+ // tx.Complete();
+ // }
+ //}
+
+
+ private void _Insert(TrackerEntities db, bool isAsync = false)
+ {
+ Locator.Current.Register(() => new MySqlBatchRunner());
+ try
+ {
+ db.Database.Log = s => System.Diagnostics.Trace.WriteLine(s);
+ db.productsummaries.Delete();
+ var query = from product in db.products
+ join item2 in (
+ from item in db.items
+ group item by item.ProductId into grItem
+ select new
+ {
+ ProductId = grItem.Key,
+ AvgPrice = grItem.Average(x => x.ListPrice + x.UnitCost)
+ }
+ ) on product.ProductId equals item2.ProductId into items
+ from item3 in items.DefaultIfEmpty()
+ select new ProductSummary2
+ {
+ ProductId = product.ProductId,
+ Name = product.Name,
+ AvgPrice = item3.AvgPrice ?? 0
+ };
+ if (isAsync) db.productsummaries.InsertAsync(query).Wait();
+ else db.productsummaries.Insert(query);
+ var source = query.ToArray();
+ var result = db.productsummaries.ToArray();
+ for (int i = 0; i < source.Length; i++)
+ {
+ source[i].AvgPrice = Math.Round(source[i].AvgPrice, 2, MidpointRounding.AwayFromZero); //In database, only two digits after decimal point
+ source[i].Verified = true; //Verified was not set in query. In database, its default value is true (1)
+ }
+ Assert.True(result.OrderBy(i => i.ProductId).SequenceEqual(source.OrderBy(i => i.ProductId), new ProductSummaryComparer()));
+
+ db.item_2.Delete();
+ var query2 = db.items.Where(item => item.ListPrice / item.UnitCost >= 5);
+ if (isAsync) db.item_2.InsertAsync(query2).Wait();
+ else db.item_2.Insert(query2);
+ var source2 = query2.ToArray().OrderBy(i => i.ItemId);
+ var result2 = db.item_2.ToArray().Select(i => ItemComparer.GetItem(i)).OrderBy(i => i.ItemId);
+ Assert.True(result2.SequenceEqual(source2, new ItemComparer()));
+
+
+ db.item_2.Delete();
+ //var query3 = from item in db.items where item.ProductId == "K9-RT-02" select item; //Using MySQL provider, ObjectQuery.Parameters is not filled if its parameter is constant
+ string productId = "K9-RT-02";
+ var query3 = from item in db.items where item.ProductId == productId select item;
+ if (isAsync) db.item_2.InsertAsync(query3).Wait();
+ else db.item_2.Insert(query3);
+ var source3 = query3.ToArray().OrderBy(item => item.ItemId);
+ var result3 = db.item_2.ToArray().Select(i => ItemComparer.GetItem(i)).OrderBy(item => item.ItemId);
+ Assert.True(result3.SequenceEqual(source3, new ItemComparer()));
+ }
+ finally
+ {
+ Locator.Current.Register(() => new SqlServerBatchRunner());
+ }
+ }
+
+ [Fact]
+ public void InsertNoTransaction()
+ {
+ using (var db = new TrackerEntities())
+ {
+ _Insert(db);
+ }
+ }
+
+ [Fact]
+ public void InsertInTransaction()
+ {
+ using (var db = new TrackerEntities())
+ using (var tx = db.Database.BeginTransaction())
+ {
+ _Insert(db);
+ tx.Commit();
+ }
+ }
+
+ /*** MySQL seems not to support TransactionScope ***/
+ //[Fact]
+ //public void InsertInTransactionScope()
+ //{
+ // using (var tx = new TransactionScope())
+ // using (var db = new TrackerEntities())
+ // {
+ // _Insert(db);
+ // tx.Complete();
+ // }
+ //}
+
+ [Fact]
+ public void InsertAsync()
+ {
+ using (var db = new TrackerEntities())
+ {
+ _Insert(db, true);
+ }
+ }
+ }
+
+ class ProductSummary2 : productsummary { }
+
+ class ProductSummaryComparer : IEqualityComparer, System.Collections.IComparer
+ {
+ public int Compare(object x, object y)
+ {
+ if (x == null && y == null) return 0;
+ var x2 = x as productsummary;
+ var y2 = y as productsummary;
+ if (x2 != null && y2 != null)
+ {
+ if (x2.ProductId == y2.ProductId
+ && x2.Name == y2.Name
+ && x2.AvgPrice == y2.AvgPrice
+ && x2.Verified == y2.Verified)
+ return 0;
+ }
+ return -1;
+ }
+
+ public bool Equals(productsummary x, productsummary y)
+ {
+ return Compare(x, y) == 0;
+ }
+
+ public int GetHashCode(productsummary obj)
+ {
+ if (obj == null) return 0;
+ return obj.ProductId.GetHashCode();
+ }
+ }
+
+ class ItemComparer : IEqualityComparer
- , System.Collections.IComparer
+ {
+ public int Compare(object x, object y)
+ {
+ if (x == null && y == null) return 0;
+ if (x == null || y == null) return -1;
+ item item = GetItem(x), item2 = GetItem(y);
+ if (item.ItemId == item2.ItemId
+ && item.ProductId == item2.ProductId
+ && item.ListPrice == item2.ListPrice
+ && item.UnitCost == item2.UnitCost
+ && item.Supplier == item2.Supplier
+ && item.Status == item2.Status
+ && item.Attr1 == item2.Attr1
+ && item.Attr2 == item2.Attr2
+ && item.Attr3 == item2.Attr3
+ && item.Attr4 == item2.Attr4
+ && item.Attr5 == item2.Attr5) return 0;
+ return -1;
+ }
+
+ public bool Equals(item x, item y)
+ {
+ return Compare(x, y) == 0;
+ }
+
+ public int GetHashCode(item obj)
+ {
+ return obj.ItemId.GetHashCode();
+ }
+
+ public static item GetItem(object obj)
+ {
+ if (obj is item) return obj as item;
+ if (obj is item_2)
+ {
+ var item2 = obj as item_2;
+ return new item
+ {
+ ItemId = item2.ItemId,
+ ProductId = item2.ProductId,
+ ListPrice = item2.ListPrice,
+ UnitCost = item2.UnitCost,
+ Supplier = item2.Supplier,
+ Status = item2.Status,
+ Attr1 = item2.Attr1,
+ Attr2 = item2.Attr2,
+ Attr3 = item2.Attr3,
+ Attr4 = item2.Attr4,
+ Attr5 = item2.Attr5
+ };
+ }
+ return null;
+ }
+ }
+}
diff --git a/Source/Samples/net45/Tracker.MySql.Test/Properties/AssemblyInfo.cs b/Source/Samples/net45/Tracker.MySql.Test/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..3b3f8b6
--- /dev/null
+++ b/Source/Samples/net45/Tracker.MySql.Test/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Tracker.MySql.Test")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Tracker.MySql.Test")]
+[assembly: AssemblyCopyright("Copyright © 2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("d8f3c9ee-afd3-4291-96f2-4dbeb842e5aa")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Source/Samples/net45/Tracker.MySql.Test/Tracker.MySql.Test.csproj b/Source/Samples/net45/Tracker.MySql.Test/Tracker.MySql.Test.csproj
new file mode 100644
index 0000000..2f7a472
--- /dev/null
+++ b/Source/Samples/net45/Tracker.MySql.Test/Tracker.MySql.Test.csproj
@@ -0,0 +1,120 @@
+
+
+
+ Debug
+ AnyCPU
+ {D8F3C9EE-AFD3-4291-96F2-4DBEB842E5AA}
+ Library
+ Properties
+ Tracker.MySql.Test
+ Tracker.MySql.Test
+ v4.5.2
+ 512
+ {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ 10.0
+ $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
+ $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages
+ False
+ UnitTest
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\..\..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.dll
+ True
+
+
+ ..\..\..\packages\MySql.Data.6.9.8\lib\net45\MySql.Data.dll
+ True
+
+
+ ..\..\..\packages\MySql.Data.Entity.6.9.8\lib\net45\MySql.Data.Entity.EF6.dll
+ True
+
+
+
+
+
+
+ ..\..\..\packages\xunit.runner.visualstudio.2.1.0\build\_common\xunit.abstractions.dll
+
+
+ ..\..\..\packages\xunit.assert.2.1.0\lib\dotnet\xunit.assert.dll
+
+
+ ..\..\..\packages\xunit.extensibility.core.2.1.0\lib\dotnet\xunit.core.dll
+
+
+ ..\..\..\packages\xunit.extensibility.execution.2.1.0\lib\net45\xunit.execution.desktop.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {d390c235-242c-4e92-9e0b-d2463e87b0f0}
+ EntityFramework.Extended.net45
+
+
+ {e445e980-4ab0-4012-8929-118b01392393}
+ Tracker.MySql.Entities
+
+
+
+
+
+
+
+
+
+
+ False
+
+
+ False
+
+
+ False
+
+
+ False
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Source/Samples/net45/Tracker.MySql.Test/packages.config b/Source/Samples/net45/Tracker.MySql.Test/packages.config
new file mode 100644
index 0000000..a1b2edf
--- /dev/null
+++ b/Source/Samples/net45/Tracker.MySql.Test/packages.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Source/Samples/net45/Tracker.SqlServer.CodeFirst/App.config b/Source/Samples/net45/Tracker.SqlServer.CodeFirst/App.config
index f93390f..062780d 100644
--- a/Source/Samples/net45/Tracker.SqlServer.CodeFirst/App.config
+++ b/Source/Samples/net45/Tracker.SqlServer.CodeFirst/App.config
@@ -10,7 +10,7 @@
-
+
diff --git a/Source/Samples/net45/Tracker.SqlServer.CodeFirst/Tracker.SqlServer.CodeFirst.csproj b/Source/Samples/net45/Tracker.SqlServer.CodeFirst/Tracker.SqlServer.CodeFirst.csproj
index db31bd7..f101e01 100644
--- a/Source/Samples/net45/Tracker.SqlServer.CodeFirst/Tracker.SqlServer.CodeFirst.csproj
+++ b/Source/Samples/net45/Tracker.SqlServer.CodeFirst/Tracker.SqlServer.CodeFirst.csproj
@@ -1,5 +1,6 @@
+
Debug
AnyCPU
@@ -15,6 +16,8 @@
..\
true
+
+
true
@@ -54,6 +57,22 @@
+
+ ..\..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll
+ True
+
+
+ ..\..\..\packages\xunit.assert.2.1.0\lib\dotnet\xunit.assert.dll
+ True
+
+
+ ..\..\..\packages\xunit.extensibility.core.2.1.0\lib\dotnet\xunit.core.dll
+ True
+
+
+ ..\..\..\packages\xunit.extensibility.execution.2.1.0\lib\net45\xunit.execution.desktop.dll
+ True
+
@@ -120,11 +139,19 @@
-
+
+ Designer
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -18,6 +28,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -30,6 +72,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -112,6 +173,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -136,6 +221,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -221,14 +320,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -237,6 +349,10 @@
+
+
+
+
@@ -513,7 +629,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -634,6 +872,72 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Source/Samples/net45/Tracker.SqlServer.Entities/Tracker.edmx.diagram b/Source/Samples/net45/Tracker.SqlServer.Entities/Tracker.edmx.diagram
index 0971141..f0f43d0 100644
--- a/Source/Samples/net45/Tracker.SqlServer.Entities/Tracker.edmx.diagram
+++ b/Source/Samples/net45/Tracker.SqlServer.Entities/Tracker.edmx.diagram
@@ -4,7 +4,7 @@
-
+
@@ -20,6 +20,14 @@
+
+
+
+
+
+
+
+
diff --git a/Source/Samples/net45/Tracker.SqlServer.Entities/packages.config b/Source/Samples/net45/Tracker.SqlServer.Entities/packages.config
index 9e8db31..2c634d7 100644
--- a/Source/Samples/net45/Tracker.SqlServer.Entities/packages.config
+++ b/Source/Samples/net45/Tracker.SqlServer.Entities/packages.config
@@ -1,4 +1,14 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Source/Samples/net45/Tracker.SqlServer.Test/BatchDbContext.cs b/Source/Samples/net45/Tracker.SqlServer.Test/BatchDbContext.cs
index 0fa818e..c75e390 100644
--- a/Source/Samples/net45/Tracker.SqlServer.Test/BatchDbContext.cs
+++ b/Source/Samples/net45/Tracker.SqlServer.Test/BatchDbContext.cs
@@ -1,8 +1,5 @@
using System;
-using System.Collections.Generic;
-using System.Data.Entity.Infrastructure;
using System.Linq;
-using System.Text;
using EntityFramework.Extensions;
using Xunit;
using Tracker.SqlServer.CodeFirst;
@@ -17,6 +14,7 @@ public class BatchDbContext
public void Delete()
{
var db = new TrackerContext();
+ db.Database.Log = s => System.Diagnostics.Trace.WriteLine(s);
string emailDomain = "@test.com";
int count = db.Users
.Where(u => u.EmailAddress.EndsWith(emailDomain))
@@ -26,6 +24,7 @@ public void Delete()
public void DeleteWhere()
{
var db = new TrackerContext();
+ db.Database.Log = s => System.Diagnostics.Trace.WriteLine(s);
string emailDomain = "@test.com";
int count = db.Users
@@ -37,6 +36,7 @@ public void DeleteWhere()
public async void DeleteAsync()
{
var db = new TrackerContext();
+ db.Database.Log = s => System.Diagnostics.Trace.WriteLine(s);
string emailDomain = "@test.com";
int count = await db.Users
@@ -48,6 +48,7 @@ public async void DeleteAsync()
public void DeleteWhereWithExpressionContainingNullParameter()
{
var db = new TrackerContext();
+ db.Database.Log = s => System.Diagnostics.Trace.WriteLine(s);
string emailDomain = "@test.com";
string optionalComparisonString = null;
@@ -61,6 +62,7 @@ public void DeleteWhereWithExpressionContainingNullParameter()
public void Update()
{
var db = new TrackerContext();
+ db.Database.Log = s => System.Diagnostics.Trace.WriteLine(s);
string emailDomain = "@test.com";
int count = db.Users
.Where(u => u.EmailAddress.EndsWith(emailDomain))
@@ -71,6 +73,7 @@ public void Update()
public async void UpdateAsync()
{
var db = new TrackerContext();
+ db.Database.Log = s => System.Diagnostics.Trace.WriteLine(s);
string emailDomain = "@test.com";
int count = await db.Users
.Where(u => u.EmailAddress.EndsWith(emailDomain))
@@ -81,6 +84,7 @@ public async void UpdateAsync()
public void UpdateAppend()
{
var db = new TrackerContext();
+ db.Database.Log = s => System.Diagnostics.Trace.WriteLine(s);
string emailDomain = "@test.com";
string newComment = " New Comment";
@@ -94,6 +98,7 @@ public void UpdateAppend()
public void UpdateAppendAndNull()
{
var db = new TrackerContext();
+ db.Database.Log = s => System.Diagnostics.Trace.WriteLine(s);
string emailDomain = "@test.com";
string newComment = " New Comment";
@@ -112,6 +117,7 @@ public void UpdateAppendAndNull()
public void UpdateJoin()
{
var db = new TrackerContext();
+ db.Database.Log = s => System.Diagnostics.Trace.WriteLine(s);
string emailDomain = "@test.com";
string space = " ";
@@ -124,6 +130,7 @@ public void UpdateJoin()
public void UpdateCopy()
{
var db = new TrackerContext();
+ db.Database.Log = s => System.Diagnostics.Trace.WriteLine(s);
string emailDomain = "@test.com";
int count = db.Users
@@ -136,6 +143,7 @@ public void UpdateWithExpressionContainingNullParameter()
{
// This test verifies that the update is interpreted correctly when the where expression uses a parameter with a null parameter
var db = new TrackerContext();
+ db.Database.Log = s => System.Diagnostics.Trace.WriteLine(s);
string emailDomain = "@test.com";
string optionalComparisonString = null;
diff --git a/Source/Samples/net45/Tracker.SqlServer.Test/ExtensionTest.cs b/Source/Samples/net45/Tracker.SqlServer.Test/ExtensionTest.cs
index 5598da6..9977111 100644
--- a/Source/Samples/net45/Tracker.SqlServer.Test/ExtensionTest.cs
+++ b/Source/Samples/net45/Tracker.SqlServer.Test/ExtensionTest.cs
@@ -1,5 +1,4 @@
using System;
-using System.Text;
using System.Collections.Generic;
using System.Linq;
using System.Transactions;
@@ -9,7 +8,6 @@
namespace Tracker.SqlServer.Test
{
-
public class ExtensionTest
{
[Fact]
@@ -70,5 +68,281 @@ public void TransactionScopeObjectContext()
}
}
+
+ private void _Insert(TrackerEntities db, bool isAsync=false)
+ {
+ db.Database.Log = s => System.Diagnostics.Trace.WriteLine(s);
+ db.ProductSummaries.Delete();
+ var query = from product in db.Products
+ join item2 in (
+ from item in db.Items
+ group item by item.ProductId into grItem
+ select new
+ {
+ ProductId = grItem.Key,
+ AvgPrice = grItem.Average(x => x.ListPrice + x.UnitCost)
+ }
+ ) on product.ProductId equals item2.ProductId into items
+ from item3 in items.DefaultIfEmpty()
+ select new ProductSummary2
+ {
+ ProductId = product.ProductId,
+ Name = product.Name,
+ AvgPrice = item3.AvgPrice ?? 0
+ };
+ if (isAsync) db.ProductSummaries.InsertAsync(query).Wait();
+ else db.ProductSummaries.Insert(query);
+ var source = query.ToArray();
+ var result = db.ProductSummaries.ToArray();
+ for (int i = 0; i < source.Length; i++)
+ {
+ source[i].AvgPrice = Math.Round(source[i].AvgPrice, 2, MidpointRounding.AwayFromZero); //In database, only two digits after decimal point
+ source[i].Verified = true; //Verified was not set in query. In database, its default value is true (1)
+ }
+ Assert.True(result.OrderBy(i => i.ProductId).SequenceEqual(source.OrderBy(i => i.ProductId), new ProductSummaryComparer()));
+
+ db.Item_2.Delete();
+ var query2 = db.Items.Where(item => item.ListPrice / item.UnitCost >= 5);
+ if (isAsync) db.Item_2.InsertAsync(query2).Wait();
+ else db.Item_2.Insert(query2);
+ var source2 = query2.ToArray().OrderBy(i => i.ItemId);
+ var result2 = db.Item_2.ToArray().Select(i => ItemComparer.GetItem(i)).OrderBy(i => i.ItemId);
+ Assert.True(result2.SequenceEqual(source2, new ItemComparer()));
+
+
+ db.Item_2.Delete();
+ var query3 = from item in db.Items where item.ProductId == "K9-RT-02" select item;
+ if (isAsync) db.Item_2.InsertAsync(query3).Wait();
+ else db.Item_2.Insert(query3);
+ var source3 = query3.ToArray().OrderBy(item => item.ItemId);
+ var result3 = db.Item_2.ToArray().Select(i => ItemComparer.GetItem(i)).OrderBy(item => item.ItemId);
+ Assert.True(result3.SequenceEqual(source3, new ItemComparer()));
+ }
+
+ [Fact]
+ public void InsertNoTransaction()
+ {
+ using (var db = new TrackerEntities())
+ {
+ _Insert(db);
+ }
+ }
+
+ [Fact]
+ public void InsertInTransaction()
+ {
+ using (var db = new TrackerEntities())
+ using (var tx = db.Database.BeginTransaction())
+ {
+ _Insert(db);
+ tx.Commit();
+ }
+ }
+
+ [Fact]
+ public void InsertInTransactionScope()
+ {
+ using (var tx = new TransactionScope())
+ using (var db = new TrackerEntities())
+ {
+ _Insert(db);
+ tx.Complete();
+ }
+ }
+
+ [Fact]
+ public void InsertAsync()
+ {
+ using (var db = new TrackerEntities())
+ {
+ _Insert(db, true);
+ }
+ }
+
+ private void _InsertBulk(TrackerEntities db, bool isAsync = false)
+ {
+ db.Database.Log = s => System.Diagnostics.Trace.WriteLine(s);
+ db.ProductSummaries.Delete();
+ db.Database.ExecuteSqlCommand("TRUNCATE TABLE ATable");
+
+ //Create 1000 random records
+ Random r = new Random();
+ int n = 1000;
+ var entities = new List();
+ int m = (int)Math.Pow(10, 8) - 1;
+ for (int i = 1; i <= n; i++)
+ {
+ entities.Add(new ProductSummary
+ {
+ ProductId = i.ToString(),
+ Name = Guid.NewGuid().ToString().Replace("-", "").PadRight(80).Substring(0, 80),
+ AvgPrice = r.Next(-m, m),
+ Verified = r.Next() % 2 == 0,
+ Date = DateTime.Now.AddDays(r.Next(-100, 100)),
+ });
+ }
+
+ var start = DateTime.Now;
+
+ if (isAsync) db.ProductSummaries.InsertAsync(entities).Wait();
+ else db.ProductSummaries.Insert(entities);
+
+ /**
+ * Compare the execution time with these two lines of commented code below
+ // * **/
+ //db.ProductSummaries.AddRange(entities);
+ //db.SaveChanges();
+
+ System.Diagnostics.Trace.WriteLine("***** Executing bulk insert (" + n + " items) takes "
+ + DateTime.Now.Subtract(start).ToString(@"hh\:mm\:ss\.ffffff"));
+
+ Assert.True(db.ProductSummaries.Count() == n);
+
+ /** Dealing with Identity Column **/
+ var entities2 = new List();
+ for (int i = 1; i <= n; i++)
+ {
+ entities2.Add(new ATable
+ {
+ A = r.NextDouble(),
+ B = Guid.NewGuid().ToString().Replace("-", "").PadRight(50).Substring(0, 50),
+ //C is an Identity column
+ D = DateTime.Now.AddDays(r.Next(-100, 100)),
+ E = r.Next() % 2 == 0,
+ });
+ }
+
+ if (isAsync) db.ATables.InsertAsync(entities2).Wait();
+ else db.ATables.Insert(entities2);
+ Assert.True(db.ATables.Count() == n);
+ }
+
+ [Fact]
+ public void InsertBulkNoTransaction()
+ {
+ using (var db = new TrackerEntities())
+ {
+ _InsertBulk(db);
+ }
+ }
+
+ [Fact]
+ public void InsertBulkInTransaction()
+ {
+ using (var db = new TrackerEntities())
+ using (var tx = db.Database.BeginTransaction())
+ {
+ _InsertBulk(db);
+ tx.Commit();
+ }
+ }
+
+ [Fact]
+ public void InsertBulkInTransactionScope()
+ {
+ using (var tx = new TransactionScope())
+ using (var db = new TrackerEntities())
+ {
+ _InsertBulk(db);
+ tx.Complete();
+ }
+ }
+
+ [Fact]
+ public void InsertBulkAsync()
+ {
+ using (var db = new TrackerEntities())
+ {
+ _InsertBulk(db, true);
+ }
+ }
+ }
+
+ class ProductSummary2 : ProductSummary { }
+
+ class ProductSummaryComparer : IEqualityComparer, System.Collections.IComparer
+ {
+ public int Compare(object x, object y)
+ {
+ if (x == null && y == null) return 0;
+ var x2 = x as ProductSummary;
+ var y2 = y as ProductSummary;
+ if (x2 != null && y2 != null)
+ {
+ if (x2.ProductId == y2.ProductId
+ && x2.Name == y2.Name
+ && x2.AvgPrice == y2.AvgPrice
+ && x2.Verified == y2.Verified)
+ return 0;
+ }
+ return -1;
+ }
+
+ public bool Equals(ProductSummary x, ProductSummary y)
+ {
+ return Compare(x, y) == 0;
+ }
+
+ public int GetHashCode(ProductSummary obj)
+ {
+ if (obj == null) return 0;
+ return obj.ProductId.GetHashCode();
+ }
+ }
+
+ class ItemComparer : IEqualityComparer
- , System.Collections.IComparer
+ {
+ public int Compare(object x, object y)
+ {
+ if (x == null && y == null) return 0;
+ if (x == null || y == null) return -1;
+ Item item = GetItem(x), item2 = GetItem(y);
+ if (item.ItemId == item2.ItemId
+ && item.ProductId == item2.ProductId
+ && item.ListPrice == item2.ListPrice
+ && item.UnitCost == item2.UnitCost
+ && item.Supplier == item2.Supplier
+ && item.Status == item2.Status
+ && item.Attr1 == item2.Attr1
+ && item.Attr2 == item2.Attr2
+ && item.Attr3 == item2.Attr3
+ && item.Attr4 == item2.Attr4
+ && item.Attr5 == item2.Attr5) return 0;
+ return -1;
+ }
+
+ public bool Equals(Item x, Item y)
+ {
+ return Compare(x, y) == 0;
+ }
+
+ public int GetHashCode(Item obj)
+ {
+ return obj.ItemId.GetHashCode();
+ }
+
+ public static Item GetItem(object obj)
+ {
+ if (obj is Item) return obj as Item;
+ if (obj is Item_2)
+ {
+ var item2 = obj as Item_2;
+ return new Item
+ {
+ ItemId = item2.ItemId,
+ ProductId = item2.ProductId,
+ ListPrice = item2.ListPrice,
+ UnitCost = item2.UnitCost,
+ Supplier = item2.Supplier,
+ Status = item2.Status,
+ Attr1 = item2.Attr1,
+ Attr2 = item2.Attr2,
+ Attr3 = item2.Attr3,
+ Attr4 = item2.Attr4,
+ Attr5 = item2.Attr5
+ };
+ }
+ return null;
+ }
}
}
diff --git a/Source/Samples/net45/Tracker.SqlServer.Test/Tracker.SqlServer.Test.csproj b/Source/Samples/net45/Tracker.SqlServer.Test/Tracker.SqlServer.Test.csproj
index a0bfffc..3f9f6b0 100644
--- a/Source/Samples/net45/Tracker.SqlServer.Test/Tracker.SqlServer.Test.csproj
+++ b/Source/Samples/net45/Tracker.SqlServer.Test/Tracker.SqlServer.Test.csproj
@@ -1,5 +1,6 @@
+
Debug
AnyCPU
@@ -15,6 +16,8 @@
..\
true
+
+
true
@@ -72,8 +75,21 @@
-
- ..\..\..\packages\xunit.1.9.2\lib\net20\xunit.dll
+
+ False
+ ..\..\..\packages\xunit.runner.visualstudio.2.1.0\build\_common\xunit.abstractions.dll
+
+
+ ..\..\..\packages\xunit.assert.2.1.0\lib\dotnet\xunit.assert.dll
+ True
+
+
+ ..\..\..\packages\xunit.extensibility.core.2.1.0\lib\dotnet\xunit.core.dll
+ True
+
+
+ ..\..\..\packages\xunit.extensibility.execution.2.1.0\lib\net45\xunit.execution.desktop.dll
+ True
@@ -96,7 +112,7 @@
{D390C235-242C-4E92-9E0B-D2463E87B0F0}
- EntityFramework.Extended
+ EntityFramework.Extended.net45
{FA68FB7C-D87E-497B-A300-F2A7827FE92C}
@@ -121,6 +137,12 @@
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+