Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/337.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/dart/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 删除托管子列表的最佳方法。一对多/亲子关系_C#_Xamarin_Realm - Fatal编程技术网

C# 删除托管子列表的最佳方法。一对多/亲子关系

C# 删除托管子列表的最佳方法。一对多/亲子关系,c#,xamarin,realm,C#,Xamarin,Realm,我的数据库中有两个托管对象,如下所示 public class Product : RealmObject { public int Id { get; set; } public string Name { get; set; } public string Date { get; set; } public RealmList<Report> Reports { get; } // child objects } 每次加载我的应用程序时,web

我的数据库中有两个托管对象,如下所示

public class Product : RealmObject
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Date { get; set; }
    public RealmList<Report> Reports { get; } // child objects
}
每次加载我的应用程序时,web hit都会获取一个产品列表,然后开始在领域数据库中管理它们,它会在TableView中显示这些产品。单击表视图中的一个产品时,将获得一个报告列表。报告列表由另一个使用产品id的web访问获取。每次我从web获取新的报告列表时,我都需要从域数据库中删除链接到一个特定产品(按id)的所有旧报告对象

这就是困惑所在。根据这一点,目前不支持级联删除。我假设这意味着删除了像上面那样的关系中的对象。因此,目前移除子对象(RealmList)而不破坏东西的最佳方法是什么。到目前为止,我已经提出了两种方法。这里有一些代码

接近A

// id is passed in as a param by function 
var reportsById = realm.All<Report>.Where(r => r.Product.Id == id).ToList();

foreach (var report in reportsById)
{
    // Delete an object with a transaction
    using (var trans = realm.BeginWrite()) 
    {
        realm.Remove(report);
        trans.Commit();
    }
}

// Then simply add the new reports to my old Product 
// Pseudo code
var newreports = getnewreports()
foreach report in newreports
   product.Reports.add(report)
//id作为参数由函数传入
var reportsById=realm.All.Where(r=>r.Product.Id==Id.ToList();
foreach(reportsById中的var报告)
{
//删除具有事务的对象
使用(var trans=realm.BeginWrite())
{
域。删除(报告);
trans.Commit();
}
}
//然后简单地将新报告添加到我的旧产品中
//伪码
var newreports=getnewreports()
新报表中的foreach报表
product.Reports.add(报告)
方法B:

// Get the current Product object
var currentProduct = realm.All<Product>.Where(p => p.Id == id).ToList().FirstOrDefault();

foreach (var report in currentProduct.Reports)
{
    // Delete an object with a transaction
    using (var trans = realm.BeginWrite()) 
    {
        realm.Remove(report);
        trans.Commit();
    }
}

// Add new reports to product again
//获取当前产品对象
var currentProduct=realm.All.Where(p=>p.Id==Id.ToList().FirstOrDefault();
foreach(currentProduct.Reports中的var报告)
{
//删除具有事务的对象
使用(var trans=realm.BeginWrite())
{
域。删除(报告);
trans.Commit();
}
}
//再次向产品添加新报告
最后,这是我用来将我的子对象(来自web的报告)添加到父对象(产品)的方法

//首先
var webReports=等待FetchWebReport();//IList类型
/...../
//然后
var currentProduct=Realm.blah()…//使用查询从领域数据库获取
foreach(webReports中的var报告)
{
//使用事务管理对象
使用(var trans=realm.BeginWrite())
{
//添加对父产品的引用
report.Parent=currentProduct;
//添加到产品中的子列表
currentProduct.Reports.Add(报告);
trans.Commit();
}
}

有人有什么想法/意见吗?请随意挑选我当前的代码。指出问题。感谢您的开发者。=)

官方领域答案-你的B几乎是对的;-)

注意以下示例使用
Write(lambda)
样式,而不是显式事务创建和提交。它有点简洁,但做同样的工作

我也在事务内部循环,而不是做很多事务。它更快,意味着相关更新的收集在单个事务中

创建一些示例层次结构

realm.Write (() => {
    for (var pid = 1; pid <= 4; ++pid) {
        var p = realm.CreateObject<Product>();
        p.Id = pid; 
        p.Name = $"Product {pid}";
        for (var rid = 1; rid <= 5; ++rid) {
            var r = realm.CreateObject<Report>();
            r.Id = rid+pid*1000; 
            r.Ref = $"Report {pid}:{rid}";
            p.Reports.Add(r);  // child object added to relationship
        }
    }
});
对样本的重要修复-使用
ToList

realm.Write(() => {
    foreach (var r in delP.Reports.ToList())  
        realm.Remove(r); 
    realm.Remove(delP);  // lastly remove the parent 
});

您在B中的方法几乎是正确的,但它忽略了一个事实,即
foreach(currentProduct.Reports中的var报告)
正在迭代一个实时列表。因为
报告
容器在您每次删除某个内容时都会更新,它将在删除所有子项之前退出循环。

不客气。通常我们都在忙着告诉人们他们不必使用
ToList
。这是一个罕见的例外;-)哈哈,很有趣,你不认为你可以告诉我这件事,或者把我链接到一个帖子上吗?我一直使用ToList。在大多数.NET代码中使用ToList没有什么错。但是,它确实会在内存中生成一个容器。RealmResults类是一个活动容器,当您更改其他线程中的对象时,它会更新。它也是惰性的,并且只在枚举结果时创建对象。如果您只有几十个对象,那么懒惰方面并不重要,但是如果您有数千个对象的结果,并且称为ToList,那么可能会在时间和堆活动方面产生显著的影响。
realm.Write (() => {
    for (var pid = 1; pid <= 4; ++pid) {
        var p = realm.CreateObject<Product>();
        p.Id = pid; 
        p.Name = $"Product {pid}";
        for (var rid = 1; rid <= 5; ++rid) {
            var r = realm.CreateObject<Report>();
            r.Id = rid+pid*1000; 
            r.Ref = $"Report {pid}:{rid}";
            p.Reports.Add(r);  // child object added to relationship
        }
    }
});
var delId = 1;
var delP = realm.All<Product>().First(p => p.Id == delId);  
if (delP == null)
  return;
realm.Write(() => {
    foreach (var r in delP.Reports.ToList())  
        realm.Remove(r); 
    realm.Remove(delP);  // lastly remove the parent 
});