Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/256.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#_.net_Asp.net Mvc_Entity Framework - Fatal编程技术网

C# 创建使用域实体的可重用类

C# 创建使用域实体的可重用类,c#,.net,asp.net-mvc,entity-framework,C#,.net,Asp.net Mvc,Entity Framework,作为一名开发人员,我试图使我的类更加模块化和可重用。我遇到问题的一个方面是当我设计一个类来处理实体框架实体时 例如,我可以创建一个购物车类,其角色是充当产品、折扣和其他与结帐相关的东西的容器。它公开了获取购物车总数的方法,并强制执行一些与购物车可以做什么和不能做什么相关的业务规则 我可能会创建一个实体框架实体,它是一个“产品”,并让我的购物车接受这个实体。无论这看起来多么方便,它在我使用购物车的项目中创建了一个不需要的对Product类的依赖。如果我想在另一个项目中重复使用购物车,“产品”实体不

作为一名开发人员,我试图使我的类更加模块化和可重用。我遇到问题的一个方面是当我设计一个类来处理实体框架实体时

例如,我可以创建一个购物车类,其角色是充当产品、折扣和其他与结帐相关的东西的容器。它公开了获取购物车总数的方法,并强制执行一些与购物车可以做什么和不能做什么相关的业务规则

我可能会创建一个实体框架实体,它是一个“产品”,并让我的购物车接受这个实体。无论这看起来多么方便,它在我使用购物车的项目中创建了一个不需要的对Product类的依赖。如果我想在另一个项目中重复使用购物车,“产品”实体不一定是相同的

如何优雅地将购物车类与实体框架解耦,这样就不会导致体系结构问题的发展

我考虑过创建一个接口IPProduct,它具有购物卡需要的相关属性和方法,然后将我的实体类作为IPProduct的实例

基本上,我正在寻找一种好的设计模式,以将我的类与项目的本地域实体解耦,无论它们可能采取何种形式

以下是我最终要做的事情;一种通用的购物车,其中T是IPProduct。然后,我将实体框架实体设置为IPProduct:

public interface IProduct
{
    /// <summary>
    /// Unique Identifier For the product.
    /// </summary>
    int Id { get; set; }
    decimal Price { get; set; }
}

public interface IShoppingCart<T> where T : IProduct
{
    /// <summary>
    /// Returns the total of all the products without any modifiers.
    /// </summary>
    decimal SubTotal { get; }

    /// <summary>
    /// Returns a total of everything in the cart, including all applicable promotions.
    /// </summary>
    decimal Total { get; }

    /// <summary>
    /// Returns a total of the discounts for the applicable promotions in the cart.
    /// </summary>
    decimal TotalDiscount { get; }

    /// <summary>
    /// Returns a count of products in the cart.
    /// </summary>
    int ProductCount { get; }

    /// <summary>
    /// Returns a count of unique products in the cart.
    /// </summary>
    int UniqueProductCount { get; }

    /// <summary>
    /// Adds a product increasing the product count if there is already one in the cart.
    /// </summary>
    /// <param name="product">Product To Add</param>
    void AddProduct(T product);

    /// <summary>
    /// Remove an instance of a product from the cart, return the product that was removed.
    /// </summary>
    /// <param name="id"></param>
    /// <returns>Instance of T</returns>
    void RemoveProduct(int id);

    /// <summary>
    /// Returns a list of the products in the cart.
    /// </summary>
    /// <returns></returns>
    IList<T> ListProducts();

    /// <summary>
    /// Remove all products from the cart;
    /// </summary>
    void ClearAllProducts();

    /// <summary>
    /// Add a promotion strategy to the cart.
    /// </summary>
    /// <param name="promotion"></param>
    void AddPromotion(IPromotion<T> promotion);
    /// <summary>
    /// Remove a promotion from the cart.
    /// </summary>
    /// <param name="promotion"></param>
    void RemovePromotion(string key);
    /// <summary>
    /// Remove all promotions from the cart.
    /// </summary>
    void ClearAllPromotions();

    /// <summary>
    /// List all of the promotions currently in the cart.
    /// </summary>
    /// <returns></returns>
    IList<IPromotion<T>> ListPromotions();

    /// <summary>
    /// Remove everything from the cart (promotions and all).
    /// </summary>
    void EmptyCart();
}
公共接口IPProduct
{
/// 
///产品的唯一标识符。
/// 
int Id{get;set;}
十进制价格{get;set;}
}
公共接口IShoppingCart,其中T:IPProduct
{
/// 
///返回不带任何修饰符的所有产品的总数。
/// 
十进制小计{get;}
/// 
///返回购物车中的所有内容,包括所有适用的促销活动。
/// 
十进制总数{get;}
/// 
///返回购物车中适用促销的总折扣。
/// 
十进制总折扣{get;}
/// 
///返回购物车中的产品计数。
/// 
int ProductCount{get;}
/// 
///返回购物车中唯一产品的计数。
/// 
int UniqueProductCount{get;}
/// 
///添加产品,如果购物车中已有产品,则增加产品数量。
/// 
///要添加的产品
无效产品(T产品);
/// 
///从购物车中删除产品实例,返回已删除的产品。
/// 
/// 
///T的实例
无效移除产品(int id);
/// 
///返回购物车中产品的列表。
/// 
/// 
IList ListProducts();
/// 
///从购物车中取出所有产品;
/// 
作废ClearAllProducts();
/// 
///将促销策略添加到购物车。
/// 
/// 
无效添加促销(i促销);
/// 
///从购物车中删除促销。
/// 
/// 
void RemovePromotion(字符串键);
/// 
///从购物车中删除所有促销活动。
/// 
作废ClearAllPromotions();
/// 
///列出购物车中当前的所有促销活动。
/// 
/// 
IList ListPromotions();
/// 
///从购物车中删除所有内容(促销和所有内容)。
/// 
void EmptyCart();
}
您可以使用实体框架的“代码优先”功能。它允许您使用代码创建域类并将它们映射到db表。在这些类中可以有方法、附加属性等


有一些限制,比如每个类必须有一个默认构造函数,关联属性必须是虚拟的。但是它们没有那么大的问题。

一种方法是使用两组类,一组表示您的POCO类,另一组表示实体框架类。您的POCO类将是Cart、Product等,并将包含所有业务逻辑。例如,当您想将产品写入数据库时,您将手动或将产品POCO类转换为实体框架产品类,如AutoMapper

作为一个想法,您可以拥有一个类,该类将围绕实体框架数据上下文进行包装,并将公开诸如AddProduct之类的方法,该方法将接受POCO类的实例。然后,此方法将其转换为实体框架产品实例,并将其写入数据库

这种方法的缺点是您必须将POCO实例转换为实体框架实例,但它允许您单独使用POCO类和实体框架类。另外,您可以定义POCO,而不必考虑数据库模式。当您调用AddProduct并执行从POCO到Entity Framework的转换时,您可以在此时决定如何将POCO实例写入数据库


编辑:另一种方法是按照@Dmitry S的建议,首先使用代码,但代码首先促进了约定而不是配置方法,这可以在创建POCO类时强制执行某些设计思想。

您使用IPProduct接口的想法是正确的

我将把可重用的购物车放在自己的程序集中——一个不知道持久性的程序集中(比如实体框架)。购物车程序集将包含应用程序的产品必须实现的
ipproduct
接口。通过这种方式,购物车逻辑可以(通过接口)在使用它的应用程序上设置需求


如果需要持久化购物车,则必须将持久化逻辑放在域层中。一个选项可能是将购物车用作代码优先实体,另一个选项是将数据映射到作为Db模型一部分的实体类。

将我的解决方案添加到原始帖子中,Thinks?