Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/272.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 实体框架与领域驱动设计_C#_Entity Framework_Domain Driven Design - Fatal编程技术网

C# 实体框架与领域驱动设计

C# 实体框架与领域驱动设计,c#,entity-framework,domain-driven-design,C#,Entity Framework,Domain Driven Design,在花了几天时间尝试用EF和DDD建立一个简单的应用程序之后,我不得不说我感到非常沮丧,并且认为我最好还是使用LINQtoSQL,忘掉DDD和EF 带EF a) 您不能有正确的只读集合 b) 当您从子项集合中删除某些内容时,您经常会发现关系无法更改,因为一个或多个外键属性是不可为null的消息 c) 没有简单的方法可以删除父项的所有子项并重新插入它们 考虑到我发现的解决办法看起来相当糟糕,所有这些对我来说几乎都是画龙点睛。是否有人设法建立了一个简单的存储库来解决这些问题 如果是的话,你能分享一些代

在花了几天时间尝试用EF和DDD建立一个简单的应用程序之后,我不得不说我感到非常沮丧,并且认为我最好还是使用LINQtoSQL,忘掉DDD和EF

带EF

a) 您不能有正确的只读集合

b) 当您从子项集合中删除某些内容时,您经常会发现关系无法更改,因为一个或多个外键属性是不可为null的消息

c) 没有简单的方法可以删除父项的所有子项并重新插入它们

考虑到我发现的解决办法看起来相当糟糕,所有这些对我来说几乎都是画龙点睛。是否有人设法建立了一个简单的存储库来解决这些问题

如果是的话,你能分享一些代码吗

另外,我知道这是一个大话题,有没有人亲身体验过大规模web应用程序中DDD的任何实际好处?我们都知道这个理论,但如果它真的值得争论的话,有一个想法就好了


好的,到目前为止,我能做的最好的事情就是使用 AsNoTracking()当我查询某些内容时。这样我就可以得到我的信息,EF就不用做任何事情了 不管它在我背后干什么。我现在可以从收藏中删除,我可以 还可以删除(谁会认为我必须为此返回sql!) 有人知道使用AsNoTracking有什么陷阱吗?据我所知,基于SQL的 在我的对象上,并填充它们或更新/删除它们,我很好。整个追踪过程 还是走得太远了


名称空间EShop.Models.Repositories
{
公共类CustomerRepository:BaseRepository,IRepository
{
public CustomerRepository():base(新的EShopData()){}
#区域核方法
公共作废插入更新(客户)
{
如果(customer.CustomerId>0)
{
//您不能使用删除,如果您使用,您将附加,然后您将与下面的地址/卡有问题
//dbContext.Entry(address).State=EntityState.Added;将失败
dbContext.Database.ExecuteSqlCommand(“从CustomerAddress中删除,其中CustomerId=@CustomerId”,新的SqlParameter(“CustomerId”,customer.CustomerId));
dbContext.Database.ExecuteSqlCommand(“从信用卡中删除,其中CustomerId=@CustomerId”,新的SqlParameter(“CustomerId”,customer.CustomerId));
foreach(customer.Addresses中的var地址)
条目(地址).State=EntityState.Added;
foreach(客户信用卡中的var卡)
dbContext.Entry(card.State=EntityState.Added;
dbContext.Entry(customer.State=EntityState.Modified;
}
其他的
{
dbContext.Entry(customer.State=EntityState.Added;
foreach(客户信用卡中的var卡)
dbContext.Entry(card.State=EntityState.Added;
foreach(customer.Addresses中的var地址)
条目(地址).State=EntityState.Added;
}
}
公共作废删除(int customerId)
{
var existingCustomer=dbContext.Customers.Find(customerId);
if(existingCustomer!=null)
{
//删除卡片
var creditCards=dbContext.creditCards.Where(c=>c.CustomerId==CustomerId);
foreach(信用卡中的var卡)
dbContext.Entry(card.State=EntityState.Deleted;
//删除地址
var addresses=dbContext.CustomerAddresses.Where(c=>c.CustomerId==CustomerId);
foreach(地址中的变量地址)
dbContext.Entry(address).State=EntityState.Deleted;
//删除篮
条目(existingCustomer).State=EntityState.Deleted;
}
}
公共客户GetById(int customerId)
{
返回dbContext.Customers.Include(“地址”).AsNoTracking().SingleOrDefault(c=>c.CustomerId==CustomerId);
}
公共IList GetPagedAndSorted(int pageNumber、int pageSize、字符串排序方式、排序方向或排序方向)
{
返回null;
}
公共作废保存()
{
dbContext.SaveChanges();
}
#端域核方法
#区域附加法
#端域附加方法
}

}

对b的响应:创建数据库时,必须级联删除(即数据库也删除所有相关的子记录)或使外键为空。那你就不会犯那个错误了。这不是EF的错,而是关系数据库处理约束的方式。您可以在EDMX、代码或使用数据库端的DDL中对此进行配置。取决于您的决定,您是如何设置项目的

对c的回应:更普遍的感觉是,删除所有子项并重新插入听起来很容易出错,而且有一种“味道”。至少只有在绝对必要的情况下我才会这么做。从性能的角度来看,更新可能更快。也许你可以重新思考一下为什么选择删除并重新插入的问题?

a)你首先想做什么?您不能将集合设置为私有,并仅公开对其进行快照的公共属性吗

b) 要从数据库中删除子实体,请使用
dbcontext.thaentityset.remove(child)
,而不是
parent.Children.remove(child)

或者,您可以通过将子对象中的外键作为主键的一部分来建立标识关系。然后
parent.Children.Remove(child)
将从数据库中删除一行

c) 看来你在做傻事。如果您提供详细信息,我将提出不同的解决方案

大话题:你的领域够复杂吗?或者你只是想申请。。。在简单的CRUD应用程序中强制使用DDD模式?什么商业规则
namespace EShop.Models.Repositories
{
public class CustomerRepository : BaseRepository, IRepository<Customer, Int32>
{
    public CustomerRepository() : base(new EShopData()) { }

    #region CoreMethods

    public void InsertOrUpdate(Customer customer)
    {
        if (customer.CustomerId > 0)
        {
            // you cannot use remove, if you do you ll attach and then you ll have issues with the address/cards below
            // dbContext.Entry<CustomerAddress>(address).State = EntityState.Added; will fail
            dbContext.Database.ExecuteSqlCommand("DELETE FROM CustomerAddress WHERE CustomerId = @CustomerId", new SqlParameter("CustomerId", customer.CustomerId));
            dbContext.Database.ExecuteSqlCommand("DELETE FROM CreditCard WHERE CustomerId = @CustomerId", new SqlParameter("CustomerId", customer.CustomerId));

            foreach (var address in customer.Addresses)
                dbContext.Entry<CustomerAddress>(address).State = EntityState.Added;
            foreach (var card in customer.CreditCards)
                dbContext.Entry<CreditCard>(card).State = EntityState.Added;

            dbContext.Entry<Customer>(customer).State = EntityState.Modified;
        }
        else
        {
            dbContext.Entry<Customer>(customer).State = EntityState.Added;
            foreach (var card in customer.CreditCards)
                dbContext.Entry<CreditCard>(card).State = EntityState.Added;
            foreach (var address in customer.Addresses)
                dbContext.Entry<CustomerAddress>(address).State = EntityState.Added;
        }
    }

    public void Delete(int customerId)
    {
        var existingCustomer = dbContext.Customers.Find(customerId);

        if (existingCustomer != null)
        {
            //delete cards
            var creditCards = dbContext.CreditCards.Where(c => c.CustomerId == customerId);
            foreach (var card in creditCards)
                dbContext.Entry<CreditCard>(card).State = EntityState.Deleted;

            //delete addresses
            var addresses = dbContext.CustomerAddresses.Where(c => c.CustomerId == customerId);
            foreach (var address in addresses)
                dbContext.Entry<CustomerAddress>(address).State = EntityState.Deleted;

            //delete basket
            dbContext.Entry<Customer>(existingCustomer).State = EntityState.Deleted;
        }
    }

    public Customer GetById(int customerId)
    {
        return dbContext.Customers.Include("Addresses").AsNoTracking().SingleOrDefault(c => c.CustomerId == customerId);
    }

    public IList<Customer> GetPagedAndSorted(int pageNumber, int pageSize, string sortBy, SortDirection sortDirection)
    {
        return null;
    }

    public void Save()
    {
        dbContext.SaveChanges();
    }

    #endregion CoreMethods


    #region AdditionalMethods

    #endregion AdditionalMethods

}
 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Web;
 using System.Web.Helpers;
 using EShop.Models.DomainModel;
 using System.Data;
 using EShop.Models.DataAccess;
 using System.Data.Objects;
 using System.Data.Entity.Infrastructure;

namespace EShop.Models.Repositories
{
public class BasketRepository : BaseRepository, IRepository<Basket, Int32>
{
    public BasketRepository() : base(new EShopData()) { }

    #region CoreMethods

    public void InsertOrUpdate(Basket basket)
    {
        var basketInDB = dbContext.Baskets.SingleOrDefault(b => b.BasketId == basket.BasketId);
        if (basketInDB == null)
            dbContext.Baskets.Add(basket);
    }

    public void Delete(int basketId)
    {
        var basket = this.GetById(basketId);
        if (basket != null)
        {
            foreach (var product in basket.BasketProducts.ToList())
            {
                basket.BasketProducts.Remove(product); //delete relationship
                dbContext.BasketProducts.Remove(product); //delete from DB
            }
            dbContext.Baskets.Remove(basket);
        }
    }

    public Basket GetById(int basketId)
    {
        // eager-load product info
        var basket = dbContext.Baskets.Include("BasketProducts")
                                      .Include("BasketProducts.Product.Brand").SingleOrDefault(b => b.BasketId == basketId);
        return basket;
    }

    public IList<Basket> GetPagedAndSorted(int pageNumber, int pageSize, string sortBy, SortDirection sortDirection)
    {
        throw new NotImplementedException();
    }

    public void Save()
    {
        dbContext.SaveChanges();
    }

    #endregion CoreMethods


    #region AdditionalMethods
    public void AddToBasket(Basket basket, Product product, int quantity)
    {
        var existingProductInBasket = dbContext.BasketProducts.Find(basket.BasketId, product.ProductId);
        if (existingProductInBasket == null)
        {
            var basketProduct = new BasketProduct()
            {
                BasketId = basket.BasketId,
                ProductId = product.ProductId,
                Quantity = quantity
            };
            basket.BasketProducts.Add(basketProduct);   
        }
        else
        {
            existingProductInBasket.Quantity = quantity;
        }
    }

    public void RemoveFromBasket(Basket basket, Product product)
    {
        var existingProductInBasket = dbContext.BasketProducts.Find(basket.BasketId, product.ProductId);
        if (existingProductInBasket != null)
        {
            basket.BasketProducts.Remove(existingProductInBasket); //delete relationship
            dbContext.BasketProducts.Remove(existingProductInBasket); //delete from DB
        }
    }

    public void RemoveFromBasket(BasketProduct basketProduct)
    {
        var basket = dbContext.Baskets.Find(basketProduct.BasketId);
        var existingProductInBasket = dbContext.BasketProducts.Find(basketProduct.BasketId, basketProduct.ProductId);
        if (basket != null && existingProductInBasket != null)
        {
            basket.BasketProducts.Remove(existingProductInBasket); //delete relationship
            dbContext.BasketProducts.Remove(existingProductInBasket); //delete from DB
        }
    }

    public void ClearBasket(Basket basket)
    {
        foreach (var product in basket.BasketProducts.ToList())
            basket.BasketProducts.Remove(product);
    }

    #endregion AdditionalMethods

}
public partial class Basket
{
    public Basket()
    {
        this.BasketProducts = new List<BasketProduct>();
    }

    public int BasketId { get; set; }
    public int? CustomerId { get; set; }
    public decimal TotalValue { get; set; }
    public DateTime Created { get; set; }
    public DateTime Modified { get; set; }

    public ICollection<BasketProduct> BasketProducts { get; private set; }

    public void AddToBasket(Product product, int quantity)
    {
        //BUSINESS LOGIC HERE
        var productInBasket = BasketProducts.SingleOrDefault(b => b.BasketId == this.BasketId &&  b.ProductId == product.ProductId);
        if (productInBasket == null)
        {
            BasketProducts.Add(new BasketProduct
            {
                BasketId = this.BasketId,
                ProductId = product.ProductId,
                Quantity = quantity
            });
        }
        else
        {
            productInBasket.Quantity = quantity;
        }
    }

    public void RemoveFromBasket(Product product)
    {
        //BUSINESS LOGIC HERE
        var prodToRemove = BasketProducts.SingleOrDefault(b => b.BasketId == this.BasketId && b.ProductId == product.ProductId);
        BasketProducts.Remove(prodToRemove);
    }
}
public class BasketRepository : BaseRepository, IRepository<Basket, Int32>
{
    public BasketRepository() : base(new EShopData()) { }

    #region CoreMethods
    //public void InsertOrUpdate(Basket basket, bool persistNow = true) { }

    public void Save(Basket basket, bool persistNow = true)
    {
        var basketInDB = dbContext.Baskets.SingleOrDefault(b => b.BasketId == basket.BasketId);
        if (basketInDB == null)
            dbContext.Baskets.Add(basket);

        if (persistNow)
            dbContext.SaveChanges();
    }

    public void Delete(int basketId, bool persistNow = true)
    {
        var basket = this.GetById(basketId);
        if (basket != null)
        {
            foreach (var product in basket.BasketProducts.ToList())
            {
                basket.BasketProducts.Remove(product); //delete relationship
                dbContext.BasketProducts.Remove(product); //delete from DB
            }
            dbContext.Baskets.Remove(basket);
        }
        if (persistNow)
            dbContext.SaveChanges();
    }

    public Basket GetById(int basketId)
    {
        // eager-load product info
        var basket = dbContext.Baskets.Include("BasketProducts")
                                      .Include("BasketProducts.Product.Brand").SingleOrDefault(b => b.BasketId == basketId);
        return basket;
    }

    public IList<Basket> GetPagedAndSorted(int pageNumber, int pageSize, string sortBy, SortDirection sortDirection)
    {
        throw new NotImplementedException();
    }

    public void SaveForUnitOfWork()
    {
        dbContext.SaveChanges();
    }