1 using System.Collections.Generic;
   2 using DomainObjects.Diagnostics;
   3 using DomainObjects.Facade.Command;
   4 using DomainObjects.Facade.Command.Function;
   5 using DomainObjects.Facade.Test;
   6 using DomainObjects.Test.Domain;
   7 using NUnit.Framework;
   8 
   9 namespace DomainObjects.Test.TestFixture
  10 {
  11   /// <summary>
  12   /// Tests the UpdateByCriteria class.
  13   /// </summary>
  14   [TestFixture]
  15   public class UpdateByCriteriaTests : DomainObjectsTestFixture
  16   {
  17     [Test]
  18     public void ExecuteUpdate()
  19     {
  20       // Create and persist a set of products to set up the unit test.
  21       // These products will be updated by criteria later in the test.
  22       ProductCategory productCategory = new ProductCategory(GenerateUniqueString(Types.ProductCategory.Field._name), GenerateUniqueString(Types.ProductCategory.Field._description)).Manage<ProductCategory>();
  23       Product product1 = new Product(productCategory, GenerateUniqueString(Types.Product.Field._name)).Manage<Product>();
  24       Product product2 = new Product(productCategory, GenerateUniqueString(Types.Product.Field._name)).Manage<Product>();
  25       PersistenceFacade.Persist(product1, product2, productCategory);
  26 
  27       // Create an update command
  28       UpdateByCriteria updateByCriteria = new UpdateByCriteria();
  29 
  30       // Specify the field to be updated along with its new value
  31       string updatedProductName = GenerateUniqueString(Types.Product.Field._name);
  32       updateByCriteria.AddUpdateField(Types.Product.Field._name, updatedProductName);
  33 
  34       // Specify which products will be updated.
  35       // They each are associated with the same ProductCategory
  36       // so use this to constrain the update.
  37       updateByCriteria.Where.AddEqualTo(Types.Product.Field._productCategoryId, productCategory.PrimaryKey[0]);
  38 
  39       // Execute the update
  40       updateByCriteria.Execute<Product>();
  41 
  42       // Ensure that our assertions below are
  43       // retrieving the values from the database
  44       // and not the local caches
  45       ClearAppDomainAndContextCache();
  46 
  47       // Validate that the products were updated with the new name.
  48       Assert.AreEqual(updatedProductName, product1.Name, "The name of product1 was updated.");
  49       Assert.AreEqual(updatedProductName, product2.Name, "The name of product2 was updated.");
  50     }
  51 
  52     /// <summary>
  53     /// Validates that an 'UPDATE TOP()' clause is generated when <see cref="UpdateByCriteria.Top"/> is specified in an UpdateByCriteria command.
  54     /// </summary>
  55     [Test]
  56     [Category(UnitTestCategory.DoesNotWorkWithOracle)]
  57     public void ExecuteUpdateWithTop()
  58     {
  59       // Create and persist a set of products to set up the unit test.
  60       // These products will be updated by criteria later in the test.
  61       ProductCategory productCategory = new ProductCategory(GenerateUniqueString(Types.ProductCategory.Field._name), GenerateUniqueString(Types.ProductCategory.Field._description)).Manage<ProductCategory>();
  62       Product product1 = new Product(productCategory, GenerateUniqueString(Types.Product.Field._name)).Manage<Product>();
  63       Product product2 = new Product(productCategory, GenerateUniqueString(Types.Product.Field._name)).Manage<Product>();
  64       PersistenceFacade.Persist(product1, product2, productCategory);
  65 
  66       // Create an update command
  67       UpdateByCriteria updateByCriteria = new UpdateByCriteria();
  68 
  69       // Specify the field to be updated along with its new value
  70       string updatedProductName = GenerateUniqueString(Types.Product.Field._name);
  71       updateByCriteria.AddUpdateField(Types.Product.Field._name, updatedProductName);
  72 
  73       // Specify which products will be updated.
  74       // They each are associated with the same ProductCategory
  75       // so use this to constrain the update.
  76       updateByCriteria.Where.AddEqualTo(Types.Product.Field._productCategoryId, productCategory.PrimaryKey[0]);
  77 
  78       // Specify that only the top 1 will be updated
  79       updateByCriteria.Top = 1;
  80 
  81       // Track the commands executed against the database
  82       CommandMonitor commandMonitor = new CommandMonitor();
  83 
  84       // Execute the update
  85       updateByCriteria.Execute<Product>();
  86 
  87       // Validate that the expected SQL statement was generated.
  88       Assert.IsTrue(commandMonitor.FirstCommandText.Contains("UPDATE TOP (1)"), "AN 'UPDATE TOP()' SQL statement was generated.");
  89 
  90       // Validate that only one product has the new name
  91       Query<Product> productQuery = new Query<Product>();
  92       productQuery.Where.AddEqualTo(Types.Product.Field._name, updatedProductName);
  93       List<Product> updatedProducts = productQuery.FindObjectSet();
  94 
  95       Assert.AreEqual(1, updatedProducts.Count, "Exactly one product was updated.");
  96 
  97       // From the updateByCriteria statement, DomainObjects generates the following SQL UPDATE statement:
  98       //
  99       // UPDATE TOP (1) PRODUCT
 100       //         SET NAME = @PRODUCT01_NAME_1
 101       // FROM    PRODUCT AS PRODUCT01
 102       // WHERE ((PRODUCT01.PRODUCT_CATEGORY_ID = @PRODUCT01_PRODUCT_CATEGORY_ID_0))
 103     }
 104 
 105     /// <summary>
 106     /// Validates that an assigned update value can be
 107     /// a Case statement, and more generally, a Field.
 108     /// </summary>
 109     [Test]
 110     public void UpdateByCriteriaWithCase()
 111     {
 112       // Create and persist a set of products to set up the unit test.
 113       // These products will be updated by criteria later in the test.
 114       ProductCategory productCategory = new ProductCategory(GenerateUniqueString(Types.ProductCategory.Field._name), GenerateUniqueString(Types.ProductCategory.Field._description)).Manage<ProductCategory>();
 115 
 116       string productName1 = GenerateUniqueString(Types.Product.Field._name);
 117       Product product1 = new Product(productCategory, productName1).Manage<Product>();
 118 
 119       string productName2 = GenerateUniqueString(Types.Product.Field._name);
 120       Product product2 = new Product(productCategory, productName2).Manage<Product>();
 121       PersistenceFacade.Persist(product1, product2, productCategory);
 122 
 123       // Create an update command
 124       UpdateByCriteria updateByCriteria = new UpdateByCriteria();
 125 
 126       // Specify the field to be updated along with its new value
 127       string updatedProductName1 = GenerateUniqueString(Types.Product.Field._name);
 128       string updatedProductName2 = GenerateUniqueString(Types.Product.Field._name);
 129 
 130       // Build a Case clause
 131       Case caseClause = new Case();
 132       Criteria when = new Criteria();
 133       when.AddEqualTo(Types.Product.Field._name, productName1);
 134       caseClause.AddCase(when, updatedProductName1);
 135 
 136       Criteria when2 = new Criteria();
 137       when2.AddEqualTo(Types.Product.Field._name, productName2);
 138       caseClause.AddCase(when2, updatedProductName2);
 139 
 140       updateByCriteria.AddUpdateField(Types.Product.Field._name, caseClause);
 141 
 142       // Specify which products will be updated.
 143       // They each are associated with the same ProductCategory
 144       // so use this to constrain the update.
 145       updateByCriteria.Where.AddEqualTo(Types.Product.Field._productCategoryId, productCategory.PrimaryKey[0]);
 146 
 147       // Execute the update
 148       updateByCriteria.Execute<Product>();
 149 
 150       // Ensure that our assertions below are
 151       // retrieving the values from the database
 152       // and not the local caches
 153       ClearAppDomainAndContextCache();
 154 
 155       // Validate that the products were updated with the new name.
 156       Assert.AreEqual(updatedProductName1, product1.Name, "The name of product1 was updated.");
 157       Assert.AreEqual(updatedProductName2, product2.Name, "The name of product2 was updated.");
 158     }
 159   }
 160 }