【问题标题】:Duplicated fields in my records, How and Where to handle them?我的记录中的重复字段,如何以及在哪里处理它们?
【发布时间】:2010-12-19 11:03:40
【问题描述】:

嗯,这不是一个普通的重复问题。因为行中某些字段(UserId 和 Name)的重复,我只需要为每个 UserId 创建一个对象 并且仍然收集该行中其他相关的唯一信息。

这不是我第一次问同样的问题,请参考My First Question About This Issue

这是我使用的数据库结构

用户表

UsedId    UserName
--------  ----------
1         Mike
2         Raul
3         Nick 

HasPrivileges 表

UsedId       PrivilegeId      
--------     --------------
1            1
1            2
1            3
2            2
2            3

权限表

PrivilegeId      Privilege
-------------    ------------
1                Create
2                Edit
3                Delete

HasMedals 表

UsedId       MedalsId      
--------     --------------
1            1
1            2
2            2
3            1

奖牌桌

MedalsId         Medal
-------------    ------------
1                C#
2                VB.NET

现在我有一个查询我的数据库的 DAL

和一个 BLL,它有两个属性 int 用于 id 和 string 用于 name 和两个列表属性 List 和 List 以及另外两个用于权限和奖牌类型的类

还有我的 asp.net 页面(作为我的表示层),它使用 ObjectDataSource 作为绑定的数据源。

我在我的 DAL 中使用一种方法来加入所有以前的表并选择 UserId、UserName、Privilege、Medal 并返回所有用户的列表。

问题是 sql 需要多次重复用户 id 和 name,每次都带有权限的值,然后再重复 id 和用户加上每个奖牌的权限价值。我只需要一个对象来容纳一个用户。

如果我刚刚选择了 UserId = 1 的查询示例结果

1   Mike   Create   C#
1   Mike   Edit     C#
1   Mike   Delete   C#
1   Mike   Create   VB.NET
1   Mike   Edit     VB.NET
1   Mike   Delete   VB.NET

关于如何以最佳方式处理这种情况的任何想法(架构和性能方面) 以及在哪里处理它-我的意思是在哪一层-。

P.S : 如果我有除 DataSet 之外的其他选项,那么我宁愿避免使用它们!

谢谢你们的时间=)

【问题讨论】:

    标签: c# asp.net ado.net webforms


    【解决方案1】:

    如果我理解正确,您正在寻找一种方法来模拟一个用户、他们的奖牌和特权。一个干净的方法是创建一个类作为视图模型,为您显式建模如下:

    public class User
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public string[] Medals { get; set; }
        public string[] Privileges { get; set; }
    }
    

    一旦你有了这个,而不是进行连接,使用 IN 语句来选择你想要的数据会更自然。这比连接更可取,因为它明确定义了您要查找的内容并避免返回重复数据,并且很容易迭代结果以填充业务对象的字段。以下是在您的示例中为 UserID = 1 执行此操作的方法:

    对于用户名信息:

    SELECT UserName 
    FROM Users 
    WHERE UserID = 1;
    

    奖牌信息:

    SELECT Medal 
    FROM Medals 
    WHERE MedalID IN
        (SELECT MedalID
         FROM HasMedals
         WHERE UserID = 1);
    

    关于特权:

    SELECT Privilege 
    FROM Privileges 
    WHERE PrivilegeID IN
        (SELECT PrivilegeID
         FROM HasPrivileges
         WHERE UserID = 1);
    

    另一种方法是使用 ORM 解决方案,例如实体框架。这将管理您的持久性,因此您可以专注于业务逻辑。

    【讨论】:

    • 简单、干净、智能!看看 ppl 提出的所有解决方案和我的解决方案!一切都很复杂...这非常出色和简单+1谢谢...我只是有几个问题希望您能提供帮助。你为什么选择子查询而不是连接,我认为子查询不快并且会影响我的应用程序性能,你怎么看 - 与连接相比 - ?......我如何使用这种方法,我是否使用单独的 Sql每个查询的数据读取器和命令或一次执行它们!?
    • 最后一件事我希望你能给我一些关于 ORM 的建议,因为我最近一直在研究并注意到 NHibernate 的建议和关于它的消息非常好......你怎么看它还是一般的 ORM 解决方案?投票并标记为答案顺便说一句......非常感谢! =))
    • 对不起,我正在尝试选择不是按 UserId 的所有记录,我只需要 DAL 具有一个选择函数,该函数返回所有具有相关权限和奖章的用户。跨度>
    【解决方案2】:

    你能试试这个运行良好的脚本吗 输入文件 UsedId 用户名 1 迈克 2 劳尔 3尼克

    nawk -F" " 'BEGIN{FS=" ";OFS=","} { if ($1==1) print $1,$2 }' 输入文件 > Create.txt

    nawk -F" " 'BEGIN{FS=" ";OFS=","} { if ($1==1) print $1,$2 }' 输入文件 > Edit.txt

    nawk -F" " 'BEGIN{FS=" ";OFS=","} { if ($1==1) print $1,$2 }' 输入文件 > Delete.txt

    cat Create.txt nawk -F"," 'BEGIN{FS=",";OFS=","} { if ($1==1) print $1,$2,(echo "Create":"C#" ") }' > UsedId_1.txt

    cat Edit.txt nawk -F"," 'BEGIN{FS=",";OFS=","} { if ($1==2) print $1,$2,(echo "Edit":"VB. NET"") }' > UsedId_2.txt

    cat Delete.txt nawk -F"," 'BEGIN{FS=",";OFS=","} { if ($1==3) print $1,$2,(echo "Delete":"Java" ") }' > UsedId_3.txt

    输出将是可以确认的 UsedId_*.txt

    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!

    第一行将比较UsedId为1表示会生成一个Create.txt文件

    2 nd 和 3 rd 很常见

    第 4 行将比较执行 1,Mike,Create,C# 5号和6号很常见 我们可以合并的所有文件

    问候, 苏雷什

    【讨论】:

    • @user394741- 首先这不是 C# 也不是 Asp.net,我认为是 PHP!我正在使用数据库,我希望它是动态的,会有成千上万的用户......对不起,我想你都搞错了!
    【解决方案3】:

    好吧,让我们从 WHERE 开始处理取回非重复记录,因为这通常是一个简单的决定。以下是您的决定:如果您可以在存储过程中使用 TSQL 消除重复项而不影响您的对象模型和代码中的所有业务规则(意味着一切都可以无缝更改)而不是在数据库级别进行.这可以在您的场景中通过在原始查询上结合使用 SELECT DISTINCT 和 INNER JOINS 来解决。

    但是,如果您想在数据库级别解决此问题,并且它修复了代码中的 1 个单一场景但破坏了另一个场景,那么在存储过程中进行操作 不是 一个好主意。在这种情况下,您可以在映射到您的对象时在 DAL 中使用 LINQ to DataSets 来过滤该特定场景的数据。 LINQ to DataSets 非常强大(或者 LINQ to Objects 也是如此)。您可以通过添加对 System.Data.DatasetExtensions 的引用来使用 LINQ to DataSets。

    编程指南(LINQ to DataSet):
    http://msdn.microsoft.com/en-us/library/bb387004.aspx

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-06
      • 2013-03-27
      • 1970-01-01
      • 1970-01-01
      • 2013-09-19
      相关资源
      最近更新 更多