1

我正在尝试在 Windows Phone 8 上与 linq 建立一对多关系。我的问题是,在 EntitySet<> 字段中,只有一个应该存储的类真正存储到数据库中。所以我做了一个简单的项目来给你我的问题的线索。有两个类 Person 和 Number。一个人可以有多个数字。

这是数字类:

[Table]
class Number
{
    [Column(IsPrimaryKey = true, IsDbGenerated = true)]
    public int NumberID { get; set; }

    [Column]
    public int PhoneNumber { get; set; }

}

和 Person 类:

[Table]
class Person
{
    private EntitySet<Number> numbers = new EntitySet<Number>();

    [Column(IsPrimaryKey = true, IsDbGenerated = true)]
    public int PersonID { get; set; }

    [Column]
    public string Name { get; set; }

    [Association(Storage = "numbers", ThisKey = "PersonID", OtherKey = "NumberID")]
    public EntitySet<Number> Numbers
    {
        get { return numbers; }
        set
        {
            numbers.Assign(value);
        }
    }
}

当我现在尝试插入一个具有三个数字的人时:

        EntitySet<Number> numbers = new EntitySet<Number>();
        DataBase db = new DataBase(App.DBConnectionString);
        Number num1 = new Number() { PhoneNumber = 111111 };
        Number num2 = new Number() { PhoneNumber = 222222 };
        Number num3 = new Number() { PhoneNumber = 333333 };
        Person person = new Person() { Name = "Donald" };
        numbers.Add(num1);
        numbers.Add(num2);
        numbers.Add(num3);
        person.Numbers = numbers;


        try
        {
            db.Persons.InsertOnSubmit(person);
            db.SubmitChanges();
        }
        catch (Exception s)
        {
            // do nothing
        }

然后尝试再次检索数据:

        DataBase db = new DataBase(App.DBConnectionString);
        string text = "";
        foreach (Person person in db.Persons)
        {
            foreach (Number num in person.Numbers)
            {
                text += num.PhoneNumber + System.Environment.NewLine;
            }
        }

        TextBlock.Text = text;

我只得到第一个电话号码“111111”。有趣的是,在第二次运行时,文本字符串包含“111111”和“222222”。这是因为在第二人称中保存了第二个电话号码,而在第三人称中保存了第三个电话号码,依此类推。因此,如果您经常这样做,您会得到:111111 222222 333333 111111 222222 333333 ...顺便说一句,如果您使用调试器跳转到“db.Persons.InsertOnSubmit(person);” 并查看“人”,其中有一个包含所有三个数字的列表。所以它应该工作......

我真的很努力,但我想不出办法让它正确。我的怀疑是关于 [Association] 属性。

这是源的链接,因此您可以根据需要获取整个图片:https ://docs.google.com/file/d/0B5G4zya_BlZyUlU0azVvbVdiajA/edit?usp=sharing

4

1 回答 1

1

我前段时间也有这个问题。我在代码中添加了几行使其消失。

Linq2SQL 有点神奇,有时事情(不)无缘无故地工作。只是为了完全确定您可能想要实施 Microsoft 提供的官方一对多解决方案:

http://msdn.microsoft.com/en-us/library/vstudio/bb386950(v=vs.100).aspx

另外我会做以下调整:

[Table]
class Number
{
    [Column(IsPrimaryKey = true, IsDbGenerated = true)]
    public int NumberID { get; set; }

    [Column]
    public int _personID { get; set; }

    [Column]
    public int PhoneNumber { get; set; }

    private EntityRef<Person> _person;
    [Association(Storage = "_person", ThisKey = "_personID", OtherKey = "PersonID", IsForeignKey = true)]
    public Person Person
    {
        get { return this._person.Entity; }
        set { 
            this._person.Entity = value;
            if (value != null)
            {
                this._personID = value.PersonID;
            }
        }
    }  
}

我会将其添加到构造函数中:

public Person()
{
    this._numbers = new EntitySet<Number>(
    delegate (Number entity)
    {
        entity.Person = this;
    },
    delegate (Number entity)
    {
        entity.Person = null;
    });
}

作为测试,我不会尝试加载整个对象。首先检查所有数字是否已进入数据库:

var numbers = db.Numbers.ToList();

这是因为 Windows Phone 上的 L2S 在读取深层对象连接时存在严重问题。一个层次很好,但更深层次的关系被忽略了。因此,如果您的 Person 类位于另一个类中,这也可能是一个问题。

编辑:您可以向数据库上下文添加选项以强制深度对象加载:

_db = new DBContext("isostore:/mydb.sdf");
DataLoadOptions loadOptions = new DataLoadOptions();
loadOptions.LoadWith<Person>(p => p.Numbers);
_db.LoadOptions = loadOptions;
于 2013-08-23T11:43:53.210 回答