本文介绍了使用一对一关系创建/更新breeze实体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 29岁程序员,3月因学历无情被辞! 我正在使用Breeze开展项目,我遇到了一些我使用一对一关系创建的实体的问题。这是一个很长的故事,但它有一个快乐的结局,所以忍受我:))I'm working on a project using Breeze and I came across a problem with some entities I had created using a one-to-one relationship. This is a bit of a long story, but it has a happy ending, so bear with me :)这是我的C#代码的缩减版本:Here is a cut down version my C# code:public class Person { [Key] public int Id { get; set; } public virtual User User { get; set; } public string FirstName { get; set; } public string LastName { get; set; }}public class User { [Key] public int Id { get; set; } [Required] public virtual Person Person { get; set; } [Required] public string EmailAddress { get; set; } [Required] public string Password { get; set; }}public class MyDbContext : DbContext { public DbSet<Person> Person { get; set; } public DbSet<User> User { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity<User>().HasRequired(x => x.Person); }}这会创建一个包含自动生成的主数据库的Persons数据库表key和带有手动输入主键的Users表,它是Persons表的子集。This creates a Persons database table with an auto generated primary key, and a Users table with a manually entered primary key, which is a subset of the Persons table.我创建这些实体,并尝试将它们保存在我的javascript中代码类似于:I create these entities, and attempt to save them in my javascript code with something like:var manager = new breeze.EntityManager('api/Db');// other breeze initialization stuff, metadata etc.var person=manager.createEntity('Person', undefined, breeze.EntityState.Detached);var user=manager.createEntity('User', undefined, breeze.EntityState.Detached);// set other fields, name, email, passworduser.Person(user);manager.addEntity(user);manager.saveChanges().then(function() { // etc当在我的BreezeController中调用SaveChanges函数我得到了这个异常:When the SaveChanges function is called in my BreezeController I get this exception:Validation error: Property: 'Person', Error: 'The Person field is required.'在检查发送到BreezeController的JSON后,我发现ID Person和User都是'-1',并且JSON没有将Person实体嵌套在User的Person属性中。所以EFContextProvider没有办法知道应该有一个关系这些对象。Upon examination of the JSON that is send to the BreezeController I find that the Id of both the Person and the User was '-1', and that the JSON did not nest the Person entity inside the Person property of the User. So there was no way for the EFContextProvider to know that there was supposed to be a relationship between these objects.我第一次尝试解决这个问题是将'Person'实体发送到后端并使用saveChanges,然后在单独的事务中发送'User'。例如:My first attempt to solve this was to send the 'Person' entity to the backend with saveChanges, then send the 'User' in a seperate transaction. Eg:manager.addEntity(person);manager.saveChanges().then(function() { user.Person(user); // this line moved from previous example, // breeze throws error here manager.addEntity(user); manager.saveChanges().then(function() { // etc使用此我从breeze.js得到了这个错误:Using this approach I got this error from breeze.js:Cannot attach an object to an EntityManager without first setting its keyor setting its entityType 'AutoGeneratedKeyType' property to something otherthan 'None' at checkEntityKey (http://localhost:12151/scripts/breeze.debug.js)所以我尝试将用户的密钥设置为保存Person时填写的值。使用user.Id(person.Id); 现在在BreezeController中我仍然得到同样的错误:So I tried to set the key on the User to be the value filled in when the Person was saved. Using "user.Id(person.Id);" Now in the BreezeController I still get the same error:Validation error: Property: 'Person', Error: 'The Person field is required.'接下来我尝试修改BreezeController的SaveChanges方法来检查传入'User'对象没有设置'Person'属性,然后在数据库中查找人员,并将其分配给调用_efContextProvider.SaveChanges(saveBundle)之前的Person;我确实丢失了代码,但是它无关紧要,因为它也无法正常工作......它在数据库中创建了一个SECOND'Person',与第一个管理器中保存的那个完全相同。 saveChanges,但它生成了一个新的主键。然而,这确实成功地将第二个人与用户联系起来。Next I tried to modify the SaveChanges method of my BreezeController to check for an incoming 'User' object which doesn't have a 'Person' property set, then Find the person in the database, and assign it to the Person before calling _efContextProvider.SaveChanges(saveBundle); I lost the code for exactly how I did this, but it's irrelevant as it didn't work properly either... It created a SECOND 'Person' in the database, exactly the same as the one that was saved in the first manager.saveChanges, but it had a new primary key generated. This did however successfully associate the second Person with the User.在一夜之间思考之后,我通过将EFContextProvider子类化为此来提出了一个有效的解决方案:After thinking about it overnight I came up with a working solution by subclassing the EFContextProvider with this:public class MyEfContextProvider : EFContextProvider<MyDbContext>{ protected override Dictionary<Type, List<EntityInfo>> BeforeSaveEntities( Dictionary<Type, List<EntityInfo>> saveMap) { AssociateOneToOne(saveMap, typeof(Person), typeof(User)); return saveMap; } private static void AssociateOneToOne(IReadOnlyDictionary<Type, List<EntityInfo>> saveMap, Type parent, Type child) { if (!(saveMap.ContainsKey(parent) && saveMap.ContainsKey(child))) return; Func<EntityInfo, object> idFunc = delegate(EntityInfo info) { var o = info.Entity; return o.GetType().GetProperty("Id").GetValue(o); }; var childProp = child.GetProperty(parent.Name); var childMap = saveMap[child].ToDictionary(idFunc, info => info.Entity); var parentMap = saveMap[parent].ToDictionary(idFunc, info => info.Entity); foreach (var childEntry in childMap) { childProp.SetValue(childEntry.Value, parentMap[childEntry.Key]); } }}现在我意识到这一直是一个很长的问题,谢谢阅读。但我唯一的问题是,为什么我必须这样做呢?这是Breeze尚未实现的东西吗?如果是这样,我的方式是否正常?Now I realise this has been a long question, and thanks for reading. But the only question I have is, why do I have to do it this way? Is this something that Breeze doesn't have implemented yet? If so, is the way I've done it ok?推荐答案你发现了一个错误...或者它对我来说。我已经提交了它,我们会在修复后通知您。You've uncovered a bug ... or so it seems to me. I have filed it and we'll let you know when it is fixed. 在不同的注释中,您的BreezeJS客户端代码有点更多的折磨比它需要的更多。为什么要创建一个未初始化的分离实体...然后添加它?On a different note, your BreezeJS client code is a little more tortured than it needs to be. Why create an uninitialized detached entity ... and then add it?行 user.Person(用户); 似乎根本不对。那会失败。我认为你的意思是 user.Person(person); 。但你也不需要。The line user.Person(user); doesn't seem right at all. That should fail. I think you meant user.Person(person);. But you won't need that either.试试这个:var manager = new breeze.EntityManager('api/Db');// other initialization stuff.// adds new, initialized Person entityvar person = manager.createEntity('Person', { // perhaps init fields: firstName, lastName });// adds new, initialized User entity, associated w/ parent Personvar user = manager.createEntity('User', { personId: person.Id(), // SETS THE KEY TO PARENT PERSON // perhaps init fields: emailAddress, password (really!?!)});manager.saveChanges().then(function() { ... etc. 更新8月8日2013 是的,提交是BreezeJS方面的修复。我们很快就会发布它......虽然你当然可以自由地获取一个中间提交。我不会...因为中间的,没有标记的提交没有正确的QA' d。Update 8 May 2013Yes, that commit is the fix on the BreezeJS side. We'll release it soon ... although of course you are free to grab an intermediate commit. I wouldn't ... because intermediate, untagged commits haven't been properly QA'd.我认为你仍然会遇到问题......这次是在EntityFramework方面.1-1在Code First中很有用;你可能想要查看此StackOverflow主题。I think you will still have a problem ... this time on the EntityFramework side. 1-1 is pretty trick in Code First; you may want to look at this StackOverflow thread.根据您的情况,我认为您需要将用户的定义更改为:To be specific to your case, I think you need to change your definition of User to this:public class User { [Key] [ForeignKey("Person")] [DatabaseGenerated(DatabaseGeneratedOption.None)] public int Id { get; set; } //[Required] public virtual Person Person { get; set; } [Required] public string EmailAddress { get; set; } [Required] public string Password { get; set; }}您不需要用户它可能会妨碍你。You shouldn't need the "Fluent API" mapping for User that you show above and it might get in the way.// DELETE THIS !!!protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity().HasRequired(x => x.Person);} FWIW, DocCode 几乎与您的人/用户相同。测试可以保存新的Northwind Order& InternationalOrder [1 ..(0,1)relationship],在 saveNorthwindTests.js 中确认模型定义和Breeze修复。FWIW, the Order/InternationalOrder relationship in DocCode is virtually the same as your Person/User. The test, "can save a new Northwind Order & InternationalOrder [1..(0,1) relationship]", in the saveNorthwindTests.js confirms the model definition and the Breeze fix.希望这会有所帮助。 这篇关于使用一对一关系创建/更新breeze实体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云!