简体   繁体   English

在M:M关系中映射弱实体

[英]Mapping a weak entity in M:M Relationship

I have a mapper function: 我有一个映射器功能:

public void Mapper(List<Item> items, List<List> lists, List<ListItem> listItems)
    {
        using (var command = Context.CreateCommand())
        {
            command.CommandText = @"SELECT ListItem.ListId, ListItem.ItemId, Item.ItemId AS ItemItemId, List.ListId AS ListListId 
                                        FROM Item INNER JOIN
                                        ListItem ON Item.ItemId = ListItem.ItemId INNER JOIN
                                        List ON ListItem.ListId = List.ListId";
            using (var reader = command.ExecuteReader())
            {
                while (reader.Read())
                {
                    int listid = (int)reader["ListId"];
                    int itemid = (int)reader["ItemId"];
                    int listlistid = (int)reader["ListId"];
                    int itemitemid = (int)reader["ItemItemId"];

                    foreach (var listitem in listItems)
                    {
                        foreach (var item in items)
                        {
                            if (item.ItemId == itemitemid && itemitemid == itemid)
                            {
                                listitem.Item = item;
                            }
                        }

                        foreach (var list in lists)
                        {
                            if (list.ListId == listlistid && listlistid == listid)
                            {
                                listitem.List = list;
                            }
                        }
                    }
                }
            }
        }
    }

My goal is that the 3 parameters of lists of entities, that I have got from my database, but I need to map the references between "List and Listitem" and "Item and ListItem". 我的目标是从数据库中获取实体列表的3个参数,但是我需要在“列表和Listitem”与“项目和ListItem”之间映射引用。

My problem is that it always seem to map the references to the LAST Item and List in its tables, for an example, if I was my last list in its Table was "Fridge" and the last Item in its table was "Milk", all listitems will have a reference to those. 我的问题是,它似乎总是将引用映射到其表中的LAST项和列表,例如,如果我是其表中的最后一个列表是“冰箱”,而表中的最后一个项目是“牛奶”,所有列表项都将引用这些列表项。

Can anyone help? 有人可以帮忙吗? And tell me if I need to provide more code in comments please. 并告诉我是否需要在注释中提供更多代码。 :) :)

EDIT: ListItem Implementation 编辑:ListItem实现

public class ListItem
{
public virtual int Amount
{
    get;
    set;
}

public virtual int Volume
{
    get;
    set;
}

public virtual string Unit
{
    get;
    set;
}

public virtual List List
{
    get;
    set;
}

public virtual Item Item
{
    get;
    set;
}

} }

The reason why all elements from listItems end up having their Item assigned to the last element in items and their List assigned to the last element in lists is because every element in listItems (see foreach ) is ultimately being assigned, unconditionally , for every ListItem in the database (see outer-most while ). 为什么从所有元素的原因listItems最终拥有自己的Item分配到最后一个元素中items和他们的List中分配到最后一个元素lists是因为在每一个元素listItems (见foreach )最终被分配, 无条件地 ,对于每一个ListItem中数据库(请参阅最外面的while )。

To explain more simply, the code you have is the logical equivalent of this pseudo-code. 为了更简单地解释,您拥有的代码与该伪代码在逻辑上等效。

foreach (db_element in db)
{
    foreach (list_element in list)
    {
        list_element.property = ...;
    }
}

Assuming 3 elements in db and 5 elements in list there would be 15 assignments (3 x 5 = 15), instead of just 3 as you may have intended. 假设db list有3个元素, list有5个元素,那么将有15个分配(3 x 5 = 15),而不是您预期的3个。

Instead, this is how you can implement a condition for matching the appropriate element from list 相反,这是您可以实现匹配list适当元素的条件的方法

foreach (db_element in db)
{
    foreach (list_element in list)
    {
        if (list_element.ItemId == db_element.ItemId &&
            list_element.ListId == db_element.ListId)
        {
             list_element.property = ...;
        }
        else
        {
             // wrong one! skip.
        }
    }
}

Here, I've changed your code for you so you can see exactly what I mean by adding the condition. 在这里,我为您更改了代码,因此您可以通过添加条件来确切地了解我的意思。

Look out for the lines where we're doing a continue . 请留意我们正在做一个地方的线路continue

public void Mapper(List<Item> items, List<List> lists, List<ListItem> listItems)
{
    using (var command = Context.CreateCommand())
    {
        command.CommandText = @"SELECT ListItem.ListId, ListItem.ItemId, Item.ItemId AS ItemItemId, List.ListId AS ListListId 
                                    FROM Item INNER JOIN
                                    ListItem ON Item.ItemId = ListItem.ItemId INNER JOIN
                                    List ON ListItem.ListId = List.ListId";
        using (var reader = command.ExecuteReader())
        {
            while (reader.Read())
            {
                int listid = (int)reader["ListId"];
                int itemid = (int)reader["ItemId"];
                int listlistid = (int)reader["ListId"];
                int itemitemid = (int)reader["ItemItemId"];

                foreach (var listitem in listItems)
                {
                    // This is the condition you're missing.
                    if (listitem.ListId != listid &&
                        listitem.ItemId != itemid)
                    {
                        continue;
                    }

                    foreach (var item in items)
                    {
                        if (item.ItemId == itemitemid && itemitemid == itemid)
                        {
                            listitem.Item = item;
                        }
                    }

                    foreach (var list in lists)
                    {
                        if (list.ListId == listlistid && listlistid == listid)
                        {
                            listitem.List = list;
                        }
                    }
                }
            }
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM