如何在目录中管理具有不同价格的产品选项






4.15/5 (6投票s)
本文提供了一种在目录中管理产品选项的简单解决方案。此解决方案适用于任意数量的选项。
引言
本文为管理产品目录中不同产品选项(例如,尺寸、颜色等)的问题提供了一种简单且可扩展的解决方案。
Data Model
在下图中,你可以看到 LINQ DBML 预览。每个产品可以与任意数量的选项(尺寸、颜色等)相关联,并且每个选项都与任意数量的值(红色、蓝色、小号、中号等)相关联。表 *Combination* 和 *CombinationDetail* 用于存储不同选项值的组合的价格。
可下载的 zip 文件中提供的 SQL 脚本将创建数据库、表、关系,并在其中填充示例数据。
在我们的示例数据库中,产品“Test Product”具有三个属性(颜色、尺寸和保修)。假设组合 Red-Small-WithWarranty 的价格 = 200。这意味着我们将在 *Combination* 表中有一行价格 = 200,并在 *CombinationDetail* 表中为每个值有一行。
此数据结构允许为产品分配任意数量的选项,并允许每个选项具有任意数量的值。
Windows 客户端应用程序
可下载的 zip 文件还包含一个 Windows Forms 项目。该项目允许用户为一组特定的选项值生成所有可能的组合,并管理不同组合的价格。
请在 *app.config* 文件中自行调整连接字符串。
生成组合并定义所有不同的价格后,就可以选择一组不同的值并检查其价格。
代码
Windows 客户端应用程序中有两个有趣的代码片段。类 CombinationBuilder
用于生成一组选项值的所有可能的组合。
public class CombinationBuilder
{
private Dictionary<int,> _counters;
private List<string> _combinationList;
public CombinationBuilder(Dictionary<int,> counters)
{
_counters = counters;
}
public List<string> CombinationList
{
get
{
return _combinationList;
}
set
{
_combinationList = value;
}
}
public void BuildCombinationString()
{
CombinationList = new List<string>();
recursion(-1, "");
}
private void recursion(int level, string previousString)
{
level++;
for (int i = 0; i < _counters[level]; i++)
{
string currentString =
previousString + i.ToString() + ",";
if (level+1 < _counters.Count)
{
recursion(level, currentString);
}
else
{
if (currentString.Length > 0)
currentString =
currentString.Remove(currentString.Length - 1);
CombinationList.Add(currentString);
}
}
}
}
此类只是生成一个如下所示的字符串列表
0,0,0
0,0,1
0,0,2
1,0,0
....
3,2,2
此列表用作在数据库中生成数据的架构。
另一个有趣的代码是获取给定值的组合的价格的查询。该查询是使用 LINQ to SQL 和 PredicateBuilder
类生成的 (http://www.albahari.com/nutshell/predicatebuilder.aspx)。
private void LoadPrice()
{
int optionCount = 0;
var predicate = PredicateBuilder.False<combinationdetail>();
foreach (var control in grpOptions.Controls)
{
if (control.GetType() == typeof(SingleOption))
{
int optionValueId = (control as SingleOption).SelectedOptionValueId;
predicate = predicate.Or(p => p.OptionValueId == optionValueId);
optionCount++;
}
}
ProductOptionsDataContext productOptionsDataContext =
new ProductOptionsDataContext();
var combination = productOptionsDataContext
.CombinationDetails
.Where(predicate)
.GroupBy(p=> p.Combination)
.Where(p=> p.Count()==optionCount)
.Select(p=>p.Key);
decimal price = 0;
if (combination.Count() == 1)
{
price = combination.Single().Price;
}
else
{
//If no combination is found the main product price will be displayed
price = SelectedProduct.Price;
}
lblPrice.Text = string.Format("Price = {0}", price.ToString());
}
注意
大量的选项和选项值可能会生成大量的不同组合。也许在这种情况下,为任何组合定义不同的价格没有用处,因此最好不要在数据库中生成所有组合,而只生成那些具有特定价格的组合。示例代码中未提供此解决方案,但很容易实现。