티스토리 뷰

Previous Platforms

Rx, Linq Tips

kaki104 2012. 5. 4. 15:00
반응형

Rx 사용한 소스 정리 중 사용한 버전은 Rx SDK 1.1.11011

 

//기본 Linq 쿼리

var cards = from kkk in op.Entities
            where kkk.Cards != null && kkk.Cards.Any() == true
            let c = kkk.Cards
            from jjj in c
            select new UserCard(this.CommonDomainContext, kkk, jjj);

var cards2 = from kkk in op.Entities
             where kkk.Cards == null || kkk.Cards.Any() == false
             select new UserCard(this.CommonDomainContext, kkk, null);

var tcards = cards.Concat(cards2).OrderBy(p => p.User.Name);

 

//옵저버블로 만들고, 스레드 풀을 사용하고, 디스패처쓰고, 서브스크레블

tcards.ToObservable()
    .ObserveOn(Scheduler.ThreadPool)
    .ObserveOnDispatcher()
    .SubscribeOnDispatcher()
    .Subscribe(
    p =>
    {

        //next
        this.UserCards.Add(p);
    },
    c =>
    {

        //complete
    });

//레이지로 만들어서 사용해 보기도 했는데..원하는 방향이 아니였음

Lazy<ObservableCollection<UserCard>> lu = new Lazy<ObservableCollection<UserCard>>(
    () =>
    {
        ObservableCollection<UserCard> collection = new ObservableCollection<UserCard>(tcards);
        return collection;
    });

this.AllUserCards = lu.Value;

//스케줄러만 사용해서 스레드풀로 처리를 해볼려고 했는데..실행은 가능하나, 원하는 결론이 아님

Scheduler
    .Schedule(Scheduler.ThreadPool,
    sc =>
    {
        foreach (var user in op.Entities)
        {
            if (user.Cards != null && user.Cards.Any() == true)
            {
                var cards = from kkk in user.Cards
                            select new UserCard(this.CommonDomainContext, user, kkk);

                cards.ToList().ForEach(p =>
                {
                    Deployment.Current.Dispatcher.BeginInvoke(() =>
                    {
                        this.UserCards.Add(p);
                    });
                });
            }
        }
    });

//Linq subquery 사용 - Include

var orgMembers = this.ObjectContext.USERs_Proc(organizationId).ToList();
var results = from id in orgMembers
              join member in
                   (
                    from user in this.ObjectContext.Users.Include("Cards")
                    let cs = user.Cards
                    where user is Member
                          && (userName == "" || (user as Member).Name.Contains(userName))
                          && (cardId == "" || cs.Count(c => c.Id.Contains(cardId)) > 0)
                    select user
                   )
              on id equals member.Id
              select member;

//Rx 타이머

var timer = Observable.Interval(new TimeSpan(0, 0, 1))
                        .ObserveOnDispatcher();
timerDisp = timer.SubscribeOnDispatcher()
                .Subscribe(time =>
                {
                    if (this.Progress + 60 >= this.Total)
                    {
                        this.Progress = this.Total;
                        timerDisp.Dispose();
                    }
                    else
                        this.Progress += 60;
                });

 

//2개의 컬렉션을 가지고 새로운 컬렉션 생성하고, DataContext에 넣고, SubmitChange() 실행, Submitting 중 Cancel 가능

//모든 작업을 쓰레드풀에서 실행

Scheduler
      .Schedule(Scheduler.ThreadPool, () =>
  {
      var results = from kkk in cards
                    from jjj in permissionGroups
                    let d = (jjj is DoorPermissionGroup ? new CardDoorPermissionGroupRelation() { CardId = kkk.Id, GroupId = (jjj as DoorPermissionGroup).GroupId, LastState = 1 } : null)
                    let f = (jjj is FloorPermissionGroup ? new CardFloorPermissionGroupRelation() { CardId = kkk.Id, GroupId = (jjj as FloorPermissionGroup).GroupId, LastState = 1 } : null)
                    let p = (jjj is PartitionPermissionGroup ? new CardPartitionPermissionGroupRelation() { CardId = kkk.Id, GroupId = (jjj as PartitionPermissionGroup).GroupId, LastState = 1 } : null)
                    select new { door = d, floor = f, partition = p };

 

var doors = from kkk in
                (from kkkk in results
                 where kkkk.door != null
                 select kkkk.door)
            join jjj in this.Context.CardDoorPermissionGroupRelations
            on new { kkk.GroupId, kkk.CardId } equals new { jjj.GroupId, jjj.CardId } into outer
            from o in outer.DefaultIfEmpty()
            where o == null
            select kkk;
var floor = from kkk in
                (from kkkk in results
                 where kkkk.floor != null
                 select kkkk.floor)
            join jjj in this.Context.CardFloorPermissionGroupRelations
            on new { kkk.GroupId, kkk.CardId } equals new { jjj.GroupId, jjj.CardId } into outer
            from o in outer.DefaultIfEmpty()
            where o == null
            select kkk;
var partition = from kkk in
                    (from kkkk in results
                     where kkkk.partition != null
                     select kkkk.partition)
                join jjj in this.Context.CardPartitionPermissionGroupRelations
                on new { kkk.GroupId, kkk.CardId } equals new { jjj.GroupId, jjj.CardId } into outer
                from o in outer.DefaultIfEmpty()
                where o == null
                select kkk;

 

//이렇게 작업하면 스케줄 취소를 했을때 오류가 발생하지 않음

doors.Cast<CardDoorPermissionGroupRelation>().ToList().ForEach(
    p => this.Context.CardDoorPermissionGroupRelations.Add(p));
floor.Cast<CardFloorPermissionGroupRelation>().ToList().ForEach(
    p => this.Context.CardFloorPermissionGroupRelations.Add(p));
partition.Cast<CardPartitionPermissionGroupRelation>().ToList().ForEach(
    p => this.Context.CardPartitionPermissionGroupRelations.Add(p));

 

      submitOp = this.Context.SubmitChanges(
                  p =>
                  {
                      //공통
                      timerDisp.Dispose();

                      if (p.HasError == false)
                      {
                          if (p.IsCanceled == false)
                          {
                              //끝까지 완료
                              this.IsCompleted = true;
                              if (this.Completed != null)
                              {
                                  this.Completed(this, EventArgs.Empty);
                              }
                          }
                          else
                          {
                              //중간에 취소
                              this.IsCanceled = true;
                              this.Context.RejectChanges();
                          }
                      }
                      else
                      {
                          p.MarkErrorAsHandled();
                          this.Context.RejectChanges();
                      }
                  }, null);
  });
 
public void Cancel()
{
    if (submitOp.CanCancel == true)
    {
        submitOp.Cancel();

    }
}

 

 

///스케줄러와 Linq를 이용해서 대량 데이터 수정

addOpDisp = Scheduler
    .Schedule(Scheduler.ThreadPool, () =>
    {
        var results = from kkk in cards
                      let ds = (from door in kkk.CardDoorPermissionGroupRelations
                                select door.LastState = 1)
                      let fs = (from floor in kkk.CardFloorPermissionGroupRelations
                                select floor.LastState = 1)
                      let ps = (from part in kkk.CardPartitionPermissionGroupRelations
                                select part.LastState = 1)
                      let state = kkk.DownState = 1
                      let sum = ds.Count() + fs.Count() + ps.Count()
                      select sum;

 

        foreach (var r in results)
        {
        }
       
        submitOp = this.Context.SubmitChanges(
                        p =>
                        {
                            if (p.HasError == false)
                            {
                                if (p.IsCanceled == false)
                                {
                                    //끝까지 완료
                                    this.IsCompleted = true;
                                    if (this.Completed != null)
                                    {
                                        this.Completed(this, EventArgs.Empty);
                                    }
                                }
                                else
                                {
                                    //중간에 취소
                                    this.IsCanceled = true;
                                    this.Context.RejectChanges();
                                }
                            }
                            else
                            {
                                p.MarkErrorAsHandled();
                                this.Context.RejectChanges();
                            }

                            //공통
                            if (addOpDisp != null)
                                addOpDisp.Dispose();
                        }, null);

    });

반응형
댓글