Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

Abonnements

EF et N-Tiers

Même si les scenarii N-Tiers sont maintenant plus facile avec EF4 et les Self-Tracking entities, je pense qu’on est encore loin de la solution idéale.

Dans un post précédent, j’expliquais comment en utilisant T4, je pouvais complètement générer mon service WCF. Maintenant, qu’en est-il du tiers client ?

Dans ce même post, j’expliquais comment je pouvais “traduire” les requêtes LINQ par des paramètres de méthodes de mon service WCF.

J’ai procédé à quelques améliorations de cette partie. Cependant, mon objectif principal consistait à avoir un vrai contexte côté client. J’avais déjà fait cela pour ADO.NET Data Services en utilisant T4, J’en ai maintenant fait un pour WCF (toujours en utilisant T4 bien sûr).

Un de mes clients reproche à ADO.NET Data Services le fait que par défaut, quand on accède aux collections du contexte, on a systématiquement une requête vers le serveur. Par défaut, il voulait utiliser le cache. Avec ADO.NET Data Services, l’utilisation du cache est vraiment pas top (idem pour EF d’ailleurs).

Avec mon contexte, j’utilise par défaut le cache et j’utilise l’extension method AsQueryable pour générer une requête côté serveur.

Plutôt qu’un long discours, rien de tel que du code pour comprendre ce que fait mon contexte et en l’occurrence, les tests unitaires qui m’ont permis de valider le bon fonctionnement de mon code.

[TestClass]
public class UnitTest
{
    [TestMethod]
    public void TestService()
    {
        INorthwindService context = new NorthwindClientContext();
        Assert.AreNotEqual(0, context.GetCustomers().Count);
   
 

    [TestMethod]
    public void TestFilter()
    {
        INorthwindService context = new NorthwindClientContext();
        Assert.AreEqual(1, context.GetCustomers(null, "it.CustomerID='ALFKI'", null, null, null).Count);
   
  
    [TestMethod]
    public void TestLINQWhere()
    {
        using (var context = new NorthwindClientContext())
        {
            Assert.AreEqual(1, (from c in context.Customers.AsQueryable()
                                where c.CustomerID == "ALFKI"
                                select c).Count());
        }
   
  
    [TestMethod]
    public void TestLINQWhere2()
    {
        using (var context = new NorthwindClientContext())
        {
            var customerID = "ALFKI";
            Assert.AreEqual(1, (from c in context.Customers.AsQueryable()
                                where c.CustomerID == customerID
                                select c).Count());
        }
   
  
    [TestMethod]
    public void TestLINQWhere3()
    {
        using (var context = new NorthwindClientContext())
        {
            var customer = new Customer { CustomerID = "ALFKI" };
            Assert.AreEqual(1, (from c in context.Customers.AsQueryable()
                                where c.CustomerID == customer.CustomerID
                                select c).Count());
        }
    }  
  
    [TestMethod]
    public void TestLINQWhere4()
    {
        using (var context = new NorthwindClientContext())
        {
            Assert.AreNotEqual(0, (from o in context.Orders.AsQueryable()
                                   where o.OrderDate > new DateTime(1997, 1, 31)
                                   select o).Count());
        }
    }

   
[TestMethod]
    public void TestLINQWhere5()
    {
        using (var context = new NorthwindClientContext())
        {
            var d = new DateTime(1997, 1, 31);
            Assert.AreNotEqual(0, (from o in context.Orders.AsQueryable()
                                   where o.OrderDate > d
                                   select o).Count());
        }
    }  

    [TestMethod]
    public void TestLINQTake()
    {
        using (var context = new NorthwindClientContext())
        {
            Assert.AreEqual(2, (from c in context.Customers.AsQueryable()
                                select c).Take(2).Count());
        }
   
  
    [TestMethod]
    public void TestFirstAndInclude()
    {
        using (var context = new NorthwindClientContext())
        {
            var order = (from o in context.Orders.AsQueryable().Include(Order.CUSTOMER_NAME).Include(Order.ORDERDETAILS_NAME)
                         where o.ShipCity == "PARIS"
                         orderby o.OrderDate
                         select o).Skip(2).First();
            Assert.IsNotNull(order.Customer);
            Assert.AreEqual(1, context.Customers.Count);
            Assert.AreEqual(order.Customer, context.Customers[0]);
            Assert.AreEqual(1, context.Orders.Count);
            Assert.AreEqual(order, context.Orders[0]);
            Assert.AreNotEqual(0, order.OrderDetails);
        }
   
  
    [TestMethod]
    public void NoTracking()
    {
        using (var context = new NorthwindClientContext())
        {
            context.MergeOption = MergeOption.NoTracking;
            var l = context.Customers.AsQueryable().ToList();
            Assert.AreEqual(0, context.Customers.Count);
            Assert.AreNotEqual(0, l.Count);
        }
   
  
    [TestMethod]
    public void AppendOnly()
    {
        using (var context = new NorthwindClientContext())
        {
            context.MergeOption = MergeOption.AppendOnly;
            var l = context.Customers.AsQueryable().ToList();
            Assert.AreEqual(l.Count, context.Customers.Count);
        }
   
  
    [TestMethod]
    public void AppendOnly2()
    {
        using (var context = new NorthwindClientContext())
        {
            context.MergeOption = MergeOption.AppendOnly;
            var c = new Customer { CustomerID = "ALFKI" };
            context.Customers.Attach(c);
            context.Customers.AsQueryable().ToList();
            Assert.IsNull(c.CompanyName);
            Assert.AreEqual(0, c.ChangeTracker.ModifiedProperties.Count);
        }
   
  
    [TestMethod]
    public void OverwriteChanges()
    {
        using (var context = new NorthwindClientContext())
        {
            context.MergeOption = MergeOption.OverwriteChanges;
            var l = context.Customers.AsQueryable().ToList();
            Assert.AreEqual(l.Count, context.Customers.Count);
        }
   
  
    [TestMethod]
    public void OverwriteChanges2()
    {
        using (var context = new NorthwindClientContext())
        {
            context.MergeOption = MergeOption.OverwriteChanges;
            var c = new Customer { CustomerID = "ALFKI" };
            context.Customers.Attach(c);
            context.Customers.AsQueryable().ToList();
            Assert.IsNotNull(c.CompanyName);
            Assert.AreEqual(0, c.ChangeTracker.ModifiedProperties.Count);
        }
   
  
    [TestMethod]
    public void PreserveChanges()
    {
        using (var context = new NorthwindClientContext())
        {
            context.MergeOption = MergeOption.PreserveChanges;
            var l = context.Customers.AsQueryable().ToList();
            Assert.AreEqual(l.Count, context.Customers.Count);
        }
   
  
    [TestMethod]
    public void PreserveChanges2()
    {
        using (var context = new NorthwindClientContext())
        {
            context.MergeOption = MergeOption.PreserveChanges;
            var c = new Customer { CustomerID = "ALFKI" };
            context.Customers.Attach(c);
            context.Customers.AsQueryable().ToList();
            Assert.IsNull(c.CompanyName);
            Assert.AreNotEqual(0, c.ChangeTracker.ModifiedProperties.Count);
            Assert.IsTrue(c.ChangeTracker.ModifiedProperties.Contains("CompanyName"));
        }
   
  
    [TestMethod]
    public void Save()
    {
        using (var context = new NorthwindClientContext())
        {
            //Add
            var psCount = context.Products.AsQueryable().Count();
            var p = new Product { ProductName = "p" };
            context.Products.Add(p);
            context.SaveChanges();
            Assert.AreNotEqual(0, p.ProductID);
            Assert.AreEqual(ObjectState.Unchanged, p.ChangeTracker.State);
            Assert.AreEqual(psCount + 1, context.Products.AsQueryable().ToList().Count); 
  
            //Update
            p.ProductName = "p2";
            Assert.AreEqual(1, p.ChangeTracker.ModifiedProperties.Count);
            Assert.AreEqual("ProductName", p.ChangeTracker.ModifiedProperties[0]);
            context.SaveChanges();
            context.MergeOption = MergeOption.NoTracking;
            var p2 = context.Products.AsQueryable().Where(pr => pr.ProductID == p.ProductID).First();
            Assert.AreNotEqual(p, p2);
            Assert.AreEqual("p2", p2.ProductName); 
  
            //Remove
            context.Products.Remove(p);
            Assert.AreEqual(ObjectState.Deleted, p.ChangeTracker.State);
            context.SaveChanges();
            Assert.AreEqual(psCount, context.Products.AsQueryable().ToList().Count);
        }
   
  
    [TestMethod]
    public void Save2()
    {
        using (var context = new NorthwindClientContext())
        {
            var csCount = context.Categories.AsQueryable().Count();
            var c1 = new Category { CategoryName = "cn" };
            context.Categories.Add(c1);
            var psCount = context.Products.AsQueryable().Count();
            var p1 = new Product { ProductName = "p1" };
            var p2 = new Product { ProductName = "p2" };
            context.Products.Add(p1);
            context.Products.Add(p2);
            context.SaveChanges();
            using (var context2 = new NorthwindClientContext())
            {
                Assert.AreEqual(csCount + 1, context2.Categories.AsQueryable().Count());
                Assert.AreEqual(psCount + 2, context2.Products.AsQueryable().Count());
            }
            context.Categories.Remove(c1);
            context.Products.Remove(p1);
            p2.ProductName = "p2Bis";
            context.SaveChanges();
            using (var context2 = new NorthwindClientContext())
            {
                Assert.AreEqual(csCount, context2.Categories.AsQueryable().Count());
                Assert.AreEqual(psCount + 1, context2.Products.AsQueryable().Count());
                Assert.AreEqual("p2Bis", context2.Products.Last().ProductName);
            }
            context.Products.Remove(p2);
            context.SaveChanges();
            using (var context2 = new NorthwindClientContext())
            {
                Assert.AreEqual(psCount, context2.Products.AsQueryable().Count());
            }
        }
   
  
    [TestMethod]
    public void TestSaveManyToMany()
    {
        CustomerDemographic cd;
        using (var context = new NorthwindClientContext())
        {
            cd = new CustomerDemographic { CustomerTypeID = "CD", CustomerDesc = "cd desc" };
            context.CustomerDemographics.Add(cd);
            context.SaveChanges();
        }
        using (var context = new NorthwindClientContext())
        {
            var c = context.Customers.AsQueryable().First();
            c.CustomerDemographics.Add(cd);
            Assert.AreEqual(ObjectState.Unchanged, cd.ChangeTracker.State);
            Assert.AreEqual(1, context.CustomerDemographics.Count);
            Assert.AreEqual(1, cd.Customers.Count);
            context.SaveChanges();
        }
        using (var context = new NorthwindClientContext())
        {
            var c = context.Customers.AsQueryable().Include(Customer.CUSTOMERDEMOGRAPHICS_NAME).First();
            Assert.AreNotEqual(0, context.CustomerDemographics.Count);
            Assert.AreNotEqual(0, cd.Customers.Count);
            context.CustomerDemographics.Remove(context.CustomerDemographics.First(cd2 => cd2.CustomerTypeID.TrimEnd() == "CD"));
            context.SaveChanges();
        }
   
  
    [TestMethod]
    public void TestAddViaCollection()
    {
        using (var context = new NorthwindClientContext())
        {
            int psCount;
            using (var context2 = new NorthwindClientContext())
            {
                psCount = context2.Products.AsQueryable().Count();
            }
            var c = context.Categories.AsQueryable().First();
            var p = new Product { ProductName = "pn" };
            c.Products.Add(p);
            Assert.AreEqual(1, c.Products.Count);
            Assert.AreEqual(1, context.Products.Count);
            Assert.AreEqual(context.Products[0], p);
            Assert.AreEqual(p.Category, c);
            Assert.AreEqual(p.CategoryID, c.Id);
            Assert.AreEqual(ObjectState.Added, p.ChangeTracker.State);
            context.SaveChanges();
            using (var context2 = new NorthwindClientContext())
            {
                Assert.AreEqual(psCount + 1, context2.Products.AsQueryable().Count());
            }
            Assert.AreEqual(1, c.Products.Count);
            context.Products.Remove(p);
            Assert.AreEqual(0, c.Products.Count);
            context.SaveChanges();
        }
   
  
    [TestMethod]
    public void TestAddViaCollection2()
    {
        using (var context = new NorthwindClientContext())
        {
            int psCount;
            using (var context2 = new NorthwindClientContext())
            {
                psCount = context2.Products.AsQueryable().Count();
            }
            var c = context.Categories.AsQueryable().First();
            var p = new Product { ProductName = "pn", Category = c };
            Assert.AreEqual(1, c.Products.Count);
            Assert.AreEqual(1, context.Products.Count);
            Assert.AreEqual(context.Products[0], p);
            Assert.AreEqual(p.Category, c);
            Assert.AreEqual(p.CategoryID, c.Id);
            Assert.AreEqual(ObjectState.Added, p.ChangeTracker.State);
            context.SaveChanges();
            using (var context2 = new NorthwindClientContext())
            {
                Assert.AreEqual(psCount + 1, context2.Products.AsQueryable().Count());
            }
            Assert.AreEqual(1, c.Products.Count);
            context.Products.Remove(p);
            Assert.AreEqual(0, c.Products.Count);
            context.SaveChanges();
        }
   
  
    [TestMethod]
    public void TestAddViaCollection3()
    {
        using (var context = new NorthwindClientContext())
        {
            var c = new Category { CategoryName = "cn" };
            context.Categories.Add(c);
            var p = new Product { ProductName = "pn", Category = c };
            Assert.AreEqual(1, c.Products.Count);
            Assert.AreEqual(1, context.Products.Count);
            Assert.AreEqual(context.Products[0], p);
            Assert.AreEqual(c, p.Category);
            Assert.AreEqual(c.Id, p.CategoryID);
            Assert.AreEqual(1, context.Categories.Count);
            Assert.AreEqual(c, context.Categories[0]);
            context.SaveChanges();
            Assert.AreEqual(c, p.Category);
            Assert.AreEqual(c.Id, p.CategoryID);
            Assert.AreEqual(1, c.Products.Count);
            Assert.AreEqual(p, c.Products[0]);
            context.Categories.Remove(c);
            Assert.IsNull(p.Category);
            Assert.IsNull(p.CategoryID);
            Assert.AreEqual(ObjectState.Modified, p.ChangeTracker.State);
            Assert.AreEqual(1, p.ChangeTracker.ModifiedProperties.Count);
            Assert.AreEqual("CategoryID", p.ChangeTracker.ModifiedProperties[0]);
            context.SaveChanges();
            context.Products.Remove(p);
            context.SaveChanges();
        }
   
  
    [TestMethod]
    public void TestAddViaCollection4()
    {
        using (var context = new NorthwindClientContext())
        {
            var c = new Category { CategoryName = "cn" };
            var p = new Product { ProductName = "pn", Category = c };
            context.Categories.Add(c);
            Assert.AreEqual(1, c.Products.Count);
            Assert.AreEqual(1, context.Products.Count);
            Assert.AreEqual(context.Products[0], p);
            Assert.AreEqual(p.Category, c);
            Assert.AreEqual(p.CategoryID, c.Id);
            Assert.AreEqual(1, context.Categories.Count);
            Assert.AreEqual(c, context.Categories[0]);
        }
   
  
    [TestMethod]
    public void TestAddViaCollection5()
    {
        using (var context = new NorthwindClientContext())
        {
            var c = new Customer { CustomerID = "A" };
            var cd = new CustomerDemographic();
            c.CustomerDemographics.Add(cd);
            context.Customers.Attach(c);
            Assert.AreEqual(1, context.Customers.Count);
            Assert.AreEqual(1, context.CustomerDemographics.Count);
            Assert.AreEqual(c, context.Customers[0]);
            Assert.AreEqual(cd, context.CustomerDemographics[0]);
            Assert.AreEqual(1, cd.Customers.Count);
        }
   
  
    [TestMethod]
    [ExpectedException(typeof(InvalidOperationException))]
    public void TestEntitySetAttachWithSameKey()
    {
        using (var context = new NorthwindClientContext())
        {
            context.Categories.Attach(new Category { Id = 1 });
            context.Categories.Attach(new Category { Id = 1 });
        }
   
  
    [TestMethod]
    [ExpectedException(typeof(InvalidOperationException))]
    public void TestEntitySetAddWithSameKey()
    {
        using (var context = new NorthwindClientContext())
        {
            context.Customers.Add(new Customer { CustomerID = "C" });
            context.Customers.Add(new Customer { CustomerID = "C" });
        }
   
  
    [TestMethod]
    public void TestEntitySetAddWithSameKeyIdentity()
    {
        using (var context = new NorthwindClientContext())
        {
            context.Categories.Add(new Category { Id = 0 });
            context.Categories.Add(new Category { Id = 0 });
        }
   
  
    [TestMethod]
    [ExpectedException(typeof(InvalidOperationException))]
    public void TestNavigationPropertyManyAttachWithSameKey()
    {
        using (var context = new NorthwindClientContext())
        {
            var cd = new CustomerDemographic { CustomerTypeID = "CD" };
            context.CustomerDemographics.Attach(cd);
            context.Customers.Attach(new Customer { CustomerID = "C" });
            cd.Customers.Attach(new Customer { CustomerID = "C" });
        }
   
  
    [TestMethod]
    [ExpectedException(typeof(InvalidOperationException))]
    public void TestNavigationPropertyManyAddWithSameKey()
    {
        using (var context = new NorthwindClientContext())
        {
            var cd = new CustomerDemographic { CustomerTypeID = "CD" };
            context.CustomerDemographics.Attach(cd);
            context.Customers.Attach(new Customer { CustomerID = "C" });
            cd.Customers.Add(new Customer { CustomerID = "C" });
        }
   
  
    [TestMethod]
    public void MultipleAddAttachOfSameObject()
    {
        using (var context = new NorthwindClientContext())
        {
            var c = new Customer { CustomerID = "C" };
            context.Customers.Add(c);
            context.Customers.Add(c);
            context.Customers.Attach(c);
            new CustomerDemographic { CustomerTypeID = "CD" }.Customers.Add(c);
            Assert.AreEqual(1, context.Customers.Count);
        }
   
  
    [TestMethod]
    public void MultipleRelationAddAttachOfSameObject()
    {
        using (var context = new NorthwindClientContext())
        {
            var c = new Customer { CustomerID = "C" };
            var cd = new CustomerDemographic { CustomerTypeID = "CD" };
            c.CustomerDemographics.Add(cd);
            c.CustomerDemographics.Add(cd);
            c.CustomerDemographics.Attach(cd);
            Assert.AreEqual(1, c.CustomerDemographics.Count);
            Assert.AreEqual(1, cd.Customers.Count);
        }
   
  
    [TestMethod]
    public void DeleteCascade()
    {
        using (var context = new NorthwindClientContext())
        {
            var o = new Order();
            var od = new OrderDetail { Order = o };
            Assert.AreEqual(ObjectState.Detached, o.ChangeTracker.State);
            Assert.AreEqual(ObjectState.Detached, od.ChangeTracker.State);
            context.Orders.Add(o);
            Assert.AreEqual(ObjectState.Added, o.ChangeTracker.State);
            Assert.AreEqual(ObjectState.Added, od.ChangeTracker.State);
            context.Orders.Remove(o);
            Assert.AreEqual(ObjectState.Detached, o.ChangeTracker.State);
            Assert.AreEqual(ObjectState.Detached, od.ChangeTracker.State);
        }
   
  
    [TestMethod]
    public void DeleteCascade2()
    {
        using (var context = new NorthwindClientContext())
        {
            var o = new Order();
            var od = new OrderDetail { Order = o, Product = context.Products.AsQueryable().First(), Discount = 0, Quantity = 1, UnitPrice = 10 };
            context.Orders.Add(o);
            context.SaveChanges();
            var od2 = new OrderDetail { Order = o };
            context.Orders.Remove(o);
            Assert.AreEqual(ObjectState.Deleted, o.ChangeTracker.State);
            Assert.AreEqual(ObjectState.Deleted, od.ChangeTracker.State);
            Assert.AreEqual(ObjectState.Detached, od2.ChangeTracker.State);
            context.SaveChanges();
        }
   
  
    [TestMethod]
    public void AttachRelationInLoad()
    {
        using (var context = new NorthwindClientContext())
        {
            var c = new Category { Id = 1 };
            context.Categories.Attach(c);
            var p = new Product { CategoryID = 1 };
            context.Products.Attach(p);
            Assert.AreEqual(c, p.Category);
            Assert.AreEqual(1, c.Products.Count);
            Assert.AreEqual(p, c.Products[0]);
        }
   
  
    [TestMethod]
    public void AttachRelationInLoad2()
    {
        using (var context = new NorthwindClientContext())
        {
            var c = new Category { Id = 1 };
            context.Categories.Add(c);
            var p = new Product { CategoryID = 1 };
            context.Products.Add(p);
            Assert.AreEqual(c, p.Category);
            Assert.AreEqual(1, c.Products.Count);
            Assert.AreEqual(p, c.Products[0]);
        }
   
  
    [TestMethod]
    public void AttachRelationInLoad3()
    {
        using (var context = new NorthwindClientContext())
        {
            var p = new Product { CategoryID = 1 };
            context.Products.Attach(p);
            var c = new Category { Id = 1 };
            context.Categories.Attach(c);
            Assert.AreEqual(c, p.Category);
            Assert.AreEqual(1, c.Products.Count);
            Assert.AreEqual(p, c.Products[0]);
        }
   
  
    [TestMethod]
    public void AttachRelationInLoad4()
    {
        using (var context = new NorthwindClientContext())
        {
            var p = new Product { CategoryID = 1 };
            context.Products.Add(p);
            var c = new Category { Id = 1 };
            context.Categories.Add(c);
            Assert.AreEqual(c, p.Category);
            Assert.AreEqual(1, c.Products.Count);
            Assert.AreEqual(p, c.Products[0]);
        }
   
  
    [TestMethod]
    public void AttachRelationInLoad5()
    {
        using (var context = new NorthwindClientContext())
        {
            context.Products.AsQueryable().ToList();
            var c = context.Categories.AsQueryable().First();
            Assert.AreEqual(context.Products.Where(p => p.CategoryID == c.Id).Count(), c.Products.Count);
            foreach (var p in context.Products.Where(p => p.CategoryID == c.Id))
            {
                Assert.AreEqual(c, p.Category);
                Assert.IsTrue(c.Products.Contains(p));
            }
        }
   
  
    [TestMethod]
    public void AttachRelationInLoad6()
    {
        using (var context = new NorthwindClientContext())
        {
            var c = context.Categories.AsQueryable().First();
            context.Products.AsQueryable().ToList();
            Assert.AreEqual(context.Products.Where(p => p.CategoryID == c.Id).Count(), c.Products.Count);
            foreach (var p in context.Products.Where(p => p.CategoryID == c.Id))
            {
                Assert.AreEqual(c, p.Category);
                Assert.IsTrue(c.Products.Contains(p));
            }
        }
   
  
    [TestMethod]
    public void AttachRelationInLoad7()
    {
        using (var context = new NorthwindClientContext())
        {
            context.Products.AsQueryable().ToList();
            var c = context.Categories.AsQueryable().Include(Category.PRODUCTS_NAME).First();
            Assert.AreEqual(context.Products.Where(p => p.CategoryID == c.Id).Count(), c.Products.Count);
            foreach (var p in context.Products.Where(p => p.CategoryID == c.Id))
            {
                Assert.AreEqual(c, p.Category);
                Assert.IsTrue(c.Products.Contains(p));
            }
        }
   
  
    [TestMethod]
    public void AttachRelationInLoad8()
    {
        using (var context = new NorthwindClientContext())
        {
            context.Products.AsQueryable().ToList();
            var c = new Category { Id = 1 };
            context.Categories.Attach(c);
            var c2 = context.Categories.AsQueryable().Include(Category.PRODUCTS_NAME).First();
            Assert.AreEqual(c, c2);
            Assert.AreEqual(context.Products.Where(p => p.CategoryID == c.Id).Count(), c.Products.Count);
            foreach (var p in context.Products.Where(p => p.CategoryID == c.Id))
            {
                Assert.AreEqual(c, p.Category);
                Assert.IsTrue(c.Products.Contains(p));
            }
        }
   
  
    [TestMethod]
    public void AttachRelationInLoad9()
    {
        using (var context = new NorthwindClientContext())
        {
            var c = new Category { CategoryName = "cn" };
            var p = new Product { ProductName = "pn", Category = c };
            context.Categories.Add(c);
            Assert.AreEqual(1, context.Products.Count);
            context.SaveChanges();
            Product p2;
            using (var context2 = new NorthwindClientContext())
            {
                var c2 = context2.Categories.AsQueryable().Include(Category.PRODUCTS_NAME).Where(c3 => c3.Id == c.Id).First();
                p2 = new Product { ProductName = "pn2" };
                c2.Products.Add(p2);
                context2.SaveChanges();
            }
            var c4 = context.Categories.AsQueryable().Include(Category.PRODUCTS_NAME).Where(c3 => c3.Id == c.Id).First();
            Assert.AreEqual(c, c4);
            Assert.IsTrue(c.Products.Contains(p));
            Assert.IsFalse(c.Products.Contains(p2));
            var p3 = c.Products.First(p4 => p4.ProductID == p2.ProductID);
            Assert.IsTrue(c.Products.Contains(p3));
            Assert.IsTrue(context.Products.Contains(p3));
            context.Products.Remove(p3);
            context.Products.Remove(p);
            context.Categories.Remove(c);
            Assert.AreEqual(c.Id, p.CategoryID);
            Assert.AreEqual(c.Id, p3.CategoryID);
            context.SaveChanges();
        }
   
  
    [TestMethod]
    public void AttachRelationInLoad10()
    {
        using (var context = new NorthwindClientContext())
        {
            var p = context.Products.AsQueryable().First();
            context.Orders.Attach(new Order());
            var od = context.OrderDetails.AsQueryable().Where(od2 => od2.ProductID == p.ProductID).First();
            var p2 = (from p3 in context.Products.AsQueryable().Include(Product.CATEGORY_NAME).Include(string.Concat(Product.ORDERDETAILS_NAME, ".", OrderDetail.ORDER_NAME))
                      where p3.ProductID == p.ProductID
                      select p3).First();
            Assert.AreEqual(p, p2);
            Assert.IsNotNull(p.Category);
            Assert.AreEqual(1, context.Categories.Count);
            Assert.AreEqual(p.OrderDetails.Count, context.OrderDetails.Count);
            foreach (var od2 in p.OrderDetails)
                Assert.IsNotNull(od2.Order);
            Assert.AreEqual(p.OrderDetails.Select(od3 => od3.Order).Distinct().Count() + 1, context.Orders.Count);
            Assert.AreNotEqual(0, context.Orders.Count);
        }
   
  
    [TestMethod]
    [ExpectedException(typeof(InvalidOperationException))]
    public void AddSameEntityInDifferentContext()
    {
        var p = new Product();
        using (var context1 = new NorthwindClientContext())
        {
            context1.Products.Add(p);
            using (var context2 = new NorthwindClientContext())
            {
                context2.Products.Add(p);
            }
        }
    }  

    [TestMethod]
    [ExpectedException(typeof(InvalidOperationException))]
    public void AddSameEntityFromServiceInDifferentContext()
    {
        Product p;
        using (var context1 = new NorthwindClientContext())
        {
            p = context1.Products.AsQueryable().First();
            using (var context2 = new NorthwindClientContext())
            {
                context2.Products.Add(p);
            }
        }
   
  
    [TestMethod]
    public void AddSameEntityInDifferentContextWithDispose()
    {
        var p = new Product();
        using (var context1 = new NorthwindClientContext())
        {
            context1.Products.Add(p);
        }
        using (var context2 = new NorthwindClientContext())
        {
            context2.Products.Add(p);
        }
   


    [TestMethod]
    [ExpectedException(typeof(InvalidOperationException))]
    public void AddSameEntityInDifferentContextWithDisposeAndConflicts()
    {
        var c = new Category { Id = 1 };
        var p1 = new Product { ProductID = 1, Category = c };
        var p2 = new Product { ProductID = 2 , CategoryID = 1};
        using (var context1 = new NorthwindClientContext())
        {
            context1.Categories.Attach(c);
            context1.Products.Attach(p2);
            Assert.AreEqual(2, context1.Products.Count);
            Assert.AreEqual(2, c.Products.Count);
            Assert.AreEqual(c, p2.Category);
        }
        using (var context2 = new NorthwindClientContext())
        {
            var p3 = new Product { ProductID = 1 , CategoryID = 1};
            context2.Products.Attach(p3);
            context2.Categories.Attach(c);
        }

    }
  
    [TestMethod]
    public void LoadFromOneToMany()
    {
        using (var context = new NorthwindClientContext())
        {
            var c = context.Categories.AsQueryable().First();
            Assert.AreEqual(0, c.Products.Count);
            Assert.AreEqual(0, context.Products.Count);
            var ps = c.LoadProducts();
            Assert.AreNotEqual(0, ps.Count);
            Assert.AreEqual(ps.Count, c.Products.Count);
            Assert.AreEqual(ps.Count, context.Products.Count);
            foreach (var p in ps)
                Assert.AreEqual(c, p.Category);
        }
   
  
    [TestMethod]
    [ExpectedException(typeof(InvalidOperationException))]
    public void LoadFromOneToManyDetached()
    {
        Category c;
        using (var context = new NorthwindClientContext())
        {
            c = context.Categories.AsQueryable().First();
        }
        var ps = c.LoadProducts();
   
  
    [TestMethod]
    public void LoadFromManyToOne()
    {
        using (var context = new NorthwindClientContext())
        {
            var p = context.Products.AsQueryable().First();
            Assert.IsNull(p.Category);
            Assert.AreEqual(0, context.Categories.Count);
            var c = p.LoadCategory();
            Assert.IsNotNull(c);
            Assert.AreEqual(c, p.Category);
            Assert.AreEqual(1, context.Categories.Count);
            Assert.AreEqual(1, c.Products.Count);
            Assert.AreEqual(p, c.Products[0]);
        }
   
  
    [TestMethod]
    public void LoadFromManyToMany()
    {
        using (var context = new NorthwindClientContext())
        {
            var c = (from cust in context.Customers.AsQueryable()
                     where cust.CustomerID == "VINET"
                     select cust).First();
            Assert.AreEqual(0, c.CustomerDemographics.Count);
            Assert.AreEqual(0, context.CustomerDemographics.Count);
            c.LoadCustomerDemographics();
            Assert.AreNotEqual(0, c.CustomerDemographics.Count);
            Assert.AreEqual(c.CustomerDemographics.Count, context.CustomerDemographics.Count);
        }
   
  
    [TestMethod]
    public void LoadFromOneToOne()
    {
        using (var context = new NorthwindClientContext())
        {
            var c = context.Customers.AsQueryable().First();
            Assert.IsNull(c.Member);
            Assert.AreEqual(0, context.Members.Count);
            var m = c.LoadMember();
            Assert.IsNotNull(c.Member);
            Assert.AreEqual(1, context.Members.Count);
            Assert.AreEqual(c, m.Customer);
        }
   
  
    [TestMethod]
    public void OfType()
    {
        using (var context = new NorthwindClientContext())
        {
            var employeesInActivity = context.Employees.AsQueryable().OfType<EmployeeInActivity>().ToList();
            Assert.AreEqual(employeesInActivity.Count, context.Employees.Count);
            Assert.AreEqual(employeesInActivity.Count, context.EmployeeInActivities.Count);
            Assert.AreEqual(0, context.OutEmployees.Count);
        }
   
  
    [TestMethod]
    public void AddIntoBaseEntitySet()
    {
        using (var context = new NorthwindClientContext())
        {
            var firedEmployee = new FiredEmployee();
            context.Employees.Attach(firedEmployee);
            Assert.AreEqual(1, context.Employees.Count);
            Assert.AreEqual(1, context.OutEmployees.Count);
            Assert.AreEqual(1, context.FiredEmployees.Count);
        }
   

    [TestMethod]
    public void GetAllEntitiesWithInheritance()
    {
        using (var context = new NorthwindClientContext())
        {
            var l = context.Employees.AsQueryable().ToList();
            Assert.AreEqual(l.Count, context.Employees.Count);
            Assert.AreEqual(l.OfType<OutEmployee>().Count(), context.OutEmployees.Count);
            Assert.AreEqual(l.OfType<FiredEmployee>().Count(), context.FiredEmployees.Count);
            Assert.AreNotEqual(0, context.FiredEmployees.Count);
        }
    }  
  
    [TestMethod]
    public void Detach()
    {
        using (var context = new NorthwindClientContext())
        {
            var c = new Category { Id = 1 };
            context.Categories.Attach(c);
            var p = new Product { CategoryID = 1 };
            context.Products.Attach(p);
            Assert.AreEqual(c, p.Category);
            context.Categories.Detach(c);
            Assert.IsNull(p.Category);
            Assert.AreEqual(c.Id, p.CategoryID);
        }
   
  
    [TestMethod]
    public void UpdateFK()
    {
        using (var context = new NorthwindClientContext())
        {
            var c1 = new Category { Id = 1 };
            context.Categories.Attach(c1);
            var c2 = new Category { Id = 2 };
            context.Categories.Attach(c2);
            var p = new Product { CategoryID = 1 };
            context.Products.Attach(p);
            Assert.AreEqual(c1, p.Category);
            Assert.AreEqual(1, c1.Products.Count);
            p.CategoryID = 2;
            Assert.AreEqual(c2, p.Category);
            Assert.AreEqual(0, c1.Products.Count);
            Assert.AreEqual(1, c2.Products.Count);
        }
    }
}

Pour mes tests, j’ai utilisé l’EDM suivant:

image

En plus d’avoir un vrai contexte côté client, j’ai également procédé à une petite amélioration de l’update. Avec le template self-tracking par défaut, le SQL généré lors d’un update inclut toutes les colonnes mappées sur l’entité même si une seule a été modifiée. Avec mon implémentation, l’update ne va contenir que les colonnes modifiées. A noter que ceci n’est pas vrai pour les complex types. Si une seule propriété du complex type a été modifiée, l’update généré inclura toute les colonnes mappées sur le complex type (c’est une limitation de la version actuelle d’EF).

Pour réduire l’update généré, j’ai ajouté une liste de string ModifiedProperties dans la classe ObjectChangeTracker (pour cela, j’ai mis à jour le template T4 self-tracking types). Ensuite, j’ai également changé le template T4 self-tracking context en remplaçant :

context.ObjectStateManager.ChangeObjectState(entity, EntityState.Modified);

par

context.ObjectStateManager.ChangeObjectState(entity, EntityState.Unchanged);
var ose = context.ObjectStateManager.GetObjectStateEntry(entity);
ose.SetModified();
foreach (var propertyName in entity.ChangeTracker.ModifiedProperties) 
       ose.SetModifiedProperty(propertyName);

Si vous voulez en savoir plus sur ces templates, je vous donne rendez-vous à ma session sur EF au prochain Microsoft Tech Days à Paris et / ou au confoo à Montreal (en français également).

Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :

Publié dimanche 13 décembre 2009 17:28 par Matthieu MEZIL

Commentaires

# re: EF et N-Tiers @ dimanche 13 décembre 2009 22:04

Pour ceux qui n'aurait pas le courage de lire tous les tests (je me demande bien pourquoi Wink), en gros cela signifie que mon T4 côté client va me générer un vrai contexte un peu comme si on était côté serveur avec le contexte Entity Framework.

Matthieu MEZIL

# re: EF et N-Tiers @ lundi 14 décembre 2009 10:10

Quand tu dis côté client, tu entends côté client du service WCF ou côté client navigateur web ou autre UI?

tja

# re: EF et N-Tiers @ lundi 14 décembre 2009 10:45

@Thomas : Côté client du service WCF qui peut être une appli SL, Windows Forms, WPF, etc. Bref n'importe quoi qui va utiliser mon service WCF.

Matthieu MEZIL

# re: EF et N-Tiers @ lundi 14 décembre 2009 10:59

Ok, merci pour ta réponse. Par contre n'est-il pas dangereux de lier le client avec le contexte directement. La dépendence entre les couches me paraît trop forte.

tja

# re: EF et N-Tiers @ lundi 14 décembre 2009 11:43

omg, c'est illisible ton truc...

azra

# re: EF et N-Tiers @ lundi 14 décembre 2009 14:26

@Thomas : La dépendance ??? Justement il n'y a aucune dépendance. Ce que tu utilises ce n'est pas le contexte EF mais ma classe de contexte à moi (générée avec T4).

@Florent : je sais, je suis resté particulièrement vague d'où l'intérêt de venir voir mes sessions Smile

Matthieu MEZIL

Les commentaires anonymes sont désactivés

Les 10 derniers blogs postés

- Merci par Blog de Jérémy Jeanson le 10-01-2019, 20:47

- Office 365: Script PowerShell pour auditer l’usage des Office Groups de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 11:02

- Office 365: Script PowerShell pour auditer l’usage de Microsoft Teams de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 10:39

- Office 365: Script PowerShell pour auditer l’usage de OneDrive for Business de votre tenant par Blog Technique de Romelard Fabrice le 04-25-2019, 15:13

- Office 365: Script PowerShell pour auditer l’usage de SharePoint Online de votre tenant par Blog Technique de Romelard Fabrice le 02-27-2019, 13:39

- Office 365: Script PowerShell pour auditer l’usage d’Exchange Online de votre tenant par Blog Technique de Romelard Fabrice le 02-25-2019, 15:07

- Office 365: Script PowerShell pour auditer le contenu de son Office 365 Stream Portal par Blog Technique de Romelard Fabrice le 02-21-2019, 17:56

- Office 365: Script PowerShell pour auditer le contenu de son Office 365 Video Portal par Blog Technique de Romelard Fabrice le 02-18-2019, 18:56

- Office 365: Script PowerShell pour extraire les Audit Log basés sur des filtres fournis par Blog Technique de Romelard Fabrice le 01-28-2019, 16:13

- SharePoint Online: Script PowerShell pour désactiver l’Option IRM des sites SPO non autorisés par Blog Technique de Romelard Fabrice le 12-14-2018, 13:01