我正试图在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"one_answers"222222"。这是因为第二个人保存第二个电话号码,第三个人保存第三个电话号码等等。因此,如果你经常这样做,你会得到:111111222222333333111111222222333333。。。顺便说一句,如果您使用调试器跳转到"db.person.InsertOnSubmit(person);"看看"person",里面有一个包含所有三个数字的列表。所以它应该有效。。。
我真的很努力,但我想不出一个办法把它做好。不过,我的怀疑在于[协会]的性质。
这里有一个指向来源的链接,如果你想的话,你可以得到整个图片:https://docs.google.com/file/d/0B5G4zya_BlZyUlU0azVvbVdiajA/edit?usp=sharing
我不久前也遇到了这个问题。我在代码中添加了几行,使它消失了。
Linq2SQL有点神奇,有时事情(不)无缘无故地工作。只是为了完全确定你可能想要实现微软提供的官方一对多解决方案:
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上下文中添加选项,以强制深度对象加载:
_db = new DBContext("isostore:/mydb.sdf");
DataLoadOptions loadOptions = new DataLoadOptions();
loadOptions.LoadWith<Person>(p => p.Numbers);
_db.LoadOptions = loadOptions;