簡體   English   中英

嘗試使用Rx .Net創建數據管道

[英]Trying to create a data pipeline with Rx .Net

我一直在嘗試使用Rx .Net對某些數據進行管道傳輸,但是我真的很努力。

我有一系列未保存的Foos,其中包含一些數據。 團隊創建了酒吧的集合。 保存條之后,如果條具有BarId,則使用Foo中的數據和Bar中的BarId創建Baz。 一旦創建了Foo的所有Bar和Baz,便清除了Foo的數據並保存了Foo。 這些是類:

public class Base
{
    public Guid Id { get; set; } = Guid.Empty;

    public override string ToString()
    {
        return $"{GetType().Name}::Id:{Id}";
    }

    public Task<Unit> Save()
    {
        Id = Guid.NewGuid();

        Console.WriteLine($"{ToString()} (save)");

        return Task.FromResult(Unit.Default);
    }
}

public sealed class Foo : Base
{
    public long FooId { get; }

    public string Data { get; private set; }

    public override string ToString()
    {
        return $"{base.ToString()},FooId:{FooId},Data:{Data ?? "NULL"}";
    }

    public Task<Unit> ClearData()
    {
        Data = null;

        return Task.FromResult(Unit.Default);
    }

    public Foo(long index)
    {
        FooId = index;
        Data = $"Foo({index})";

        Console.WriteLine($"{ToString()} (ctor)");
    }
}

public class Map : Base
{
    public int Index { get; }

    public string Mapping { get; }

    public Guid BarId { get; protected set; } = Guid.Empty;

    public sealed override string ToString()
    {
        return $"{base.ToString()},Index:{Index},BarId:{BarId},Mapping:{Mapping}";
    }

    protected Map(int index, string data, Func<string, string> mapper)
    {
        Mapping = mapper(data);
        Index = index;
    }
}

public sealed class Bar : Map
{
    public Bar(int index, string data, Func<string, string> mapper) : base(index, data, mapper)
    {
        if (new Random().Next(3) > 0)
        {
            BarId = Guid.NewGuid();

            Console.WriteLine($"{ToString()} (ctor)");
        }
    }
}

public sealed class Baz : Map
{
    public Baz(int index, Guid barId, string data, Func<string, string> mapper) : base(index, data, mapper)
    {
        BarId = barId;

        Console.WriteLine($"{ToString()} (ctor)");
    }
}

我嘗試了很多事情,但這是我最想要的東西:

var foos = Observable.Interval(TimeSpan.FromSeconds(1)).Take(2).Select(i => new Foo(i));

var units = from foo in foos
            let idxs = Observable.Range(1, 3)
            from idx in idxs
            let bar = new Bar(idx, foo.Data, s => $"{s}Bar")
            from barSaved in bar.Save()
            where bar.BarId != Guid.Empty
            let baz = new Baz(idx, bar.BarId, foo.Data, s => $"{s}Baz")
            from bazSaved in baz.Save()
            from fooChanged in foo.ClearData()
            from fooSaved in foo.Save()
            select Unit.Default;

units.Subscribe();

它會創建適當數量的Bar和Baz,但每次創建保存的Baz時都會保存Foo,否則就不會保存Foo。

我希望有人可以幫助我,也許我還將學到有關反應式編程的新知識,這將有助於我更好地理解該范例。

編輯:

我嘗試將隨機數提供程序移動到靜態實例,但是沒有用。 這是顯示發生了什么的一些輸出:

Foo::Id:00000000-0000-0000-0000-000000000000,FooId:0,Data:Foo(0) (ctor)
Bar::Id:00000000-0000-0000-0000-000000000000,Index:1,BarId:00000000-0000-0000-0000-000000000000,Mapping:Foo(0)Bar (ctor)
Bar::Id:28789b8b-03d4-4160-97f2-b2cbafd80c73,Index:1,BarId:00000000-0000-0000-0000-000000000000,Mapping:Foo(0)Bar (save)
Bar::Id:00000000-0000-0000-0000-000000000000,Index:2,BarId:81e79b81-6692-406f-a025-448cd203cb73,Mapping:Foo(0)Bar (ctor)
Bar::Id:d43d2e43-b812-4657-9e4f-a5b875a595fb,Index:2,BarId:81e79b81-6692-406f-a025-448cd203cb73,Mapping:Foo(0)Bar (save)
Baz::Id:00000000-0000-0000-0000-000000000000,Index:2,BarId:81e79b81-6692-406f-a025-448cd203cb73,Mapping:Foo(0)Baz (ctor)
Baz::Id:fdf464d1-9240-49e4-89cd-dbab758159fc,Index:2,BarId:81e79b81-6692-406f-a025-448cd203cb73,Mapping:Foo(0)Baz (save)
Foo::Id:04d9d819-26bc-41dc-8f1b-a0e509acd2e5,FooId:0,Data:NULL (save)
Bar::Id:00000000-0000-0000-0000-000000000000,Index:3,BarId:6894c1f0-d776-496f-9da4-4f272a338f90,Mapping:Bar (ctor)
Bar::Id:6b82fc20-80ff-41bd-848d-a115f58392c4,Index:3,BarId:6894c1f0-d776-496f-9da4-4f272a338f90,Mapping:Bar (save)
Baz::Id:00000000-0000-0000-0000-000000000000,Index:3,BarId:6894c1f0-d776-496f-9da4-4f272a338f90,Mapping:Baz (ctor)
Baz::Id:fa361c43-ee07-44cc-8628-4835fce6da9d,Index:3,BarId:6894c1f0-d776-496f-9da4-4f272a338f90,Mapping:Baz (save)
Foo::Id:6f423cf5-8260-4d98-a0bc-4762893b5fe4,FooId:0,Data:NULL (save)
Foo::Id:00000000-0000-0000-0000-000000000000,FooId:1,Data:Foo(1) (ctor)
Bar::Id:00000000-0000-0000-0000-000000000000,Index:1,BarId:5a79b126-27d8-43a1-9bb6-4d28394d5710,Mapping:Foo(1)Bar (ctor)
Bar::Id:94f5842f-eb1c-4248-a70a-dac5eb843cc1,Index:1,BarId:5a79b126-27d8-43a1-9bb6-4d28394d5710,Mapping:Foo(1)Bar (save)
Baz::Id:00000000-0000-0000-0000-000000000000,Index:1,BarId:5a79b126-27d8-43a1-9bb6-4d28394d5710,Mapping:Foo(1)Baz (ctor)
Baz::Id:d46b1d7e-eda2-4c63-8810-830e3416e975,Index:1,BarId:5a79b126-27d8-43a1-9bb6-4d28394d5710,Mapping:Foo(1)Baz (save)
Foo::Id:e198e636-bfd7-49c5-a260-346524ec4019,FooId:1,Data:NULL (save)
Bar::Id:00000000-0000-0000-0000-000000000000,Index:2,BarId:00000000-0000-0000-0000-000000000000,Mapping:Bar (ctor)
Bar::Id:206a8796-32da-493f-9582-7c551781e2d5,Index:2,BarId:00000000-0000-0000-0000-000000000000,Mapping:Bar (save)
Bar::Id:00000000-0000-0000-0000-000000000000,Index:3,BarId:154481ad-33c3-49d7-af2b-3f7738f1f692,Mapping:Bar (ctor)
Bar::Id:ffda6907-93b0-411f-aa40-3fee790b52cb,Index:3,BarId:154481ad-33c3-49d7-af2b-3f7738f1f692,Mapping:Bar (save)
Baz::Id:00000000-0000-0000-0000-000000000000,Index:3,BarId:154481ad-33c3-49d7-af2b-3f7738f1f692,Mapping:Baz (ctor)
Baz::Id:2071927f-27d6-4df6-a74f-1c0bdfbba8d5,Index:3,BarId:154481ad-33c3-49d7-af2b-3f7738f1f692,Mapping:Baz (save)
Foo::Id:07460e6e-d3db-4ed8-a441-e16f06cd908a,FooId:1,Data:NULL (save)

如您所見,保存Baz時,Foo將清除其數據並保存,從而使所有后續的Bar和Baz丟失其數據-看到其Mapping沒有Foo(index)。

編輯:

我要實現的目標是,一旦創建並保存了Foo的所有 Bars和Bazs,則只有Foo的數據被清除並完成保存。

編輯源代碼以包括跟蹤。

我認為您的問題是if (new Random().Next(3) > 0) Random對象從系統時鍾開始播種,因此,如果快速連續調用此代碼,您將獲得相同的值。 嘗試這種方式:

public sealed class Bar : Map
{
    public static Random _rand = new Random();
    public Bar(int index, string data, Func<string, string> mapper) : base(index, data, mapper)
    {
        if (_rand.Next(3) > 0)
        {
            BarId = Guid.NewGuid();
        }
    }
}

看來可以給出正確的結果。


我將Random實例保留在方法之外,然后嘗試以下方法:

var units =
    from foo in foos
    from inner in
    (
        from idx in Observable.Range(1, 3)
        let bar = new Bar(idx, foo.Data, s => $"{s}Bar")
        from barSaved in bar.Save()
        where bar.BarId != Guid.Empty
        let baz = new Baz(idx, bar.BarId, foo.Data, s => $"{s}Baz")
        from bazSaved in baz.Save()
        select Unit.Default
    ).ToArray()
    from fooChanged in foo.ClearData()
    from fooSaved in foo.Save()
    select Unit.Default;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM