Paged Collection in Data Service

It is naturally to use Expand in a Linq query to get children collection under an entity, as showed in the following example.

using System.Collections.Generic;
using System.Linq;

public IEnumerable<User> GetMembersByGroup(string groupIdentifier)
{
  var team = this.dataContext
      // each Team has a MemberUsers collection
      .Teams.Expand(t => t.MemberUsers)
      .Where(t => t.Id == groupIdentifier)
      .Single();

  return team.MemberUsers.ToList();
}

The above code would work as long as the size of the collection is small and within server paging size of the data service (- see this blog). In order to get result from all paged collection, the following example is using DataServiceCollection<T>.Load method.

Note: The service reference needs have UseDataServiceCollection enabled in .datasvcmap configuration which should be supported by .NET 3.5 SP1 and 4. In other case, rather than System.Data.Services.Client.DataServiceCollection, the System.Collections.ObjectModel.Collection won't have Continuation.
using System.Collections.Generic;
using System.Data.Services.Client;
using System.Linq;

public IEnumerable<User> GetMembersByGroup(string groupIdentifier)
{
  var team = this.dataContext
      // expand both MemberUsers and Children teams
      .Teams.Expand("MemberUsers,Children/MemberUsers")
      .Where(t => t.Id == groupIdentifier)
      .AsEnumerable()
      .FirstOrDefault();

  if (team == null)
  {
    return new List<User>();
  }

  DataServiceCollection<User> users = team.MemberUsers;

  while (users.Continuation!= null)
  {
    users.Load(this.dataContext.Execute(users.Continuation));
  }

  return users;
}

The DataServiceCollection<T> requires a type T. For Query Projction with anonymous (or Tuple) type, the query can load data but may not support Continuation.


Another similar solution is sending data query to data service with GetContinuation.
using System.Collections.Generic;
using System.Linq;

public IEnumerable<User> GetMembersByGroup(string groupIdentifier)
{
  var dataQuery = 
        from t in this.dataContext.Teams
       where t.Id == groupIdentifier
        from u in t.MemberUsers
      select u;

  var users = this.dataContext.GetAll(dataQuery);

  return users;
}

Since only navigation query supports join operation, the query must be on the primary key (as the Id in above code); otherwise, use another query with SingleOrDefault or FirstOrDefault in prior to get the identifier. Also, GetAll method should support Query Projection, so that GetAll(dataQuery) can be used, instead of GetAll((DataServiceQuery)dataQuery).

In order to query all users by a name (which is not a navigation query), the following data query projects the result to a collection of an anonymous typed objects, so that we can get identifiers for navigation queries later.
using System.Collections.Generic;
using System.Linq;

public IEnumerable<string> GetUsersByName(string userName)
{
  var dataQuery = 
        from u in this.Users
       where u.Name == userName
      select new {
      {
        Id = u.Id, Alias = u.Alias
      }
  var result = this.dataContext.GetAll(dataQuery);
  var users = result.Select(a => a.Id);

  return users;
}

Here is the source of GetAll extension (with support of Query Projection):
using System.Collections.Generic;
using System.Data.Services.Client;
using System.Linq;

public static IEnumerable<T> GetAll<T>(this
  DataServiceContext dataContext, 
  IQueryable<T> dataServiceQuery)
{
  QueryOperationResponse<T> response = 
    (QueryOperationResponse<T>)
    ((DataServiceQuery)dataServiceQuery).Execute();

  DataServiceQueryContinuation<T> continuation = null;

  do
  {
    if (continuation != null)
    {
      response = this.dataContext.Execute(continuation);
    }

    foreach (var result in response)
    {
      yield return result;
    }

    continuation = response.GetContinuation();
  }
  while (continuation != null);
}


Paper Sizes

A0规格:1189*841mm
A1规格: 841*594mm
A2规格: 594*420mm
A3规格: 420*297mm
A4规格: 297*210mm
A5规格: 210*148mm

大度16开:211x290mm(全张:850x1168mm)
正度16开:195x271mm(全张:787x1092mm)

大度32开:140x203mm
正度32开:130x184mm
大32开:136x210mm
标准32开:127x184mm
小32开: 92x 85mm

EqualityComparer

In C#, for a list of string (or some primitive type), IEnumerable.Distinct() method can help reduce the duplicates.

var distinctList = myList.Distinct();

However, for a list of complex type, this may not work as expected, since Distinct() will produce a new list based on the hash code of each item. For any Foo type class, in order to use Distinct() method, Equals() and GetHashCode() need to be override.
public override bool Equals(object obj)
{
  Foo other = obj as Foo;
  return 
    other != null && 
    other.Name.Equals(this.Name) && 
    other.Prop.Equals(this.Prop);
}

public override int GetHashCode()
{
  var tuple = new Tuple<string, PropType>(this.Name, this.Prop);
  int hashCode = tuple.GetHashCode();
  return hashCode;
}
For hash code, see algorithms, here, and here. Do remember the rule: "If two objects compare as equal, the GetHashCode method for each object must return the same value. However, if two objects do not compare as equal, the GetHashCode methods for the two object do not have to return different values." (See more rules and guidelines on this blog)

In many cases, the developer may not own the code of class Foo to override Equals() and GetHashCode(), or the Distinct may vary in runtime. One solution is to use GroupBy method in System.Linq.Enumerable extension applying on item's property (e.g. using Name as a key to distinguish each item):
var distinctList = strList
    .GroupBy(i => i.Name)
    .Select(g => g.First())
    .ToList();

And for more than 1 key property (e.g. Prop1 and Prop2) in a group:
var distinctList = myList
    .GroupBy(i => new { i.Prop1, i.Prop2 })
    .Select(g => g.First())
    .ToList();

Same can be done with group operator using System.Linq:
var distinctList = (
    from i in recipients
    group i by new { i.Prop1, i.Prop2 } into grp
    select grp.First()).ToList();

Alternatively IEnumerable.Distinct() method can take an IEqualityComparer in the following style
var distinctList = myList.Distinct(
    EqualityFactory.Create<FooType>(
    (x, y) => x.Prop1 == y.Prop1 && x.Prop2 == y.Prop2)
    ).ToList();

Here is the source code of the factory:
// -------------------------------------
// 
//  Copyleft (c) All rights released.
// 
// -------------------------------------

namespace Common.Helpers
{
  using System;
  using System.Collections.Generic;

  /// <summary>
  /// Factory to produce instances of the <see cref="EqualityComparer{T}" /> class.
  /// the type of an object.
  /// </summary>
  public class EqualityFactory
  {
    /// <summary>
    /// Creates a new instance of the <see cref="IEqualtyComparer{T}" /> class.
    /// </summary>
    /// the type of an object.
    /// returns an instance of equality comparer.
    public static IEqualityComparer<T> Create<T>(Func<T, T, bool> funcComparer)
    {
      return new ImpEqualityComparer<T>(funcComparer);
    }

    #region internal equality comparer class

    /// <summary>
    /// Implements <see cref="IEqualityComparer" /> interface.
    /// </summary>
    /// the type of an object.
    private class ImpEqualityComparer<T> : IEqualityComparer<T>
    {
      /// <summary>the comparison function.</summary>
      private Func<T, T, bool> comparer;

      /// <summary>the default comparison function.</summary>
      private IEqualityComparer<T> defaultComparer;

      /// <summary>
      /// Initializes a new instance of the <see cref="ImpEqualityComparer{T}" /> class.
      /// </summary>
      public ImpEqualityComparer(Func<T, T, bool> delegateComparer)
      {
        this.comparer = delegateComparer;
        this.defaultComparer = EqualityComparer<T>.Default;
      }

      /// <summary>
      /// Compares objects by using equality comparer.
      /// </summary> 
      /// returns True if objects are equal; otherwise False. 
      bool IEqualityComparer<T>.Equals(T x, T y)
      {
        if (x == null && y == null) return true;
        if (x == null || y == null) return false;

        return this.comparer(x, y);
      }

      /// <summary>
      /// Get hash code by the equality comparer.
      /// </summary>
      /// returns the hash code.
      int IEqualityComparer<T>.GetHashCode(T obj)
      {
        // In order to use the comparer, the hash code has to be the same.
        return 0;
      }
    }

    #endregion
  }
}
// class EqualityFactory

If hash code comparison is required, use an LambdaEqualityComparer class instead. In the following example, the distinct result will be based on objects' Name, and other properties (Prop1 and Prop2).
var distinctList = myList.Distinct(
    new LambdaEqualityComparer<FooType>(
    (x, y) => x.Prop1 == y.Prop1 && x.Prop2 == y.Prop2,
    (t) => t.Name.GetHashCode()) // assume t.Name is a string
    ).ToList();

See LambdaEqualityComparer class source code:
// -------------------------------------
// LambdaEqualityComparer.cs
// -------------------------------------

namespace Common.Helpers
{
  using System;
  using System.Collections.Generic;

  /// <summary>
  /// Implements <see cref="IEqualityComparer" /> interface.
  /// </summary>
  /// the type of an object.
  public class LambdaEqualityComparer<T> : IEqualityComparer<T>
  {
    /// <summary>
    /// Initializes a new instance of the <see cref="LambdaEqualityComparer{T}" /> class.
    /// </summary>
    public LambdaEqualityComparer(
      Func<T, T, bool> funcEquals, Func<T, int> funcGetHashCode = null)
    {
      if (funcEquals == null)
      {
        throw new ArgumentNullException("funcEquals", "An equals function is required.");
      }

      this.GetHashCodeMethod = funcGetHashCode;
      this.EqualsMethod = funcEquals;
    }

    /// <summary>Gets and sets the method used to compute equals.</summary>
    public Func<T, T, bool> EqualsMethod { get; private set; }

    /// <summary>Gets and sets the method used to compute a hash code.</summary>
    public Func<T, int> GetHashCodeMethod { get; private set; }

    /// <summary>
    /// Implements Equals from <see cref="IEqualityComparer{T}" /> interface.
    /// </summary>
    /// returns result of the comparison.
    bool IEqualityComparer<T>.Equals(T x, T y)
    {
      return this.EqualsMethod(x, y);
    }

    /// <summary>
    /// Implements GetHashCode from <see cref="IEqualityComparer{T}" /> interface.
    /// </summary>
    /// returns hash code.
    int IEqualityComparer<T>.GetHashCode(T obj)
    {
      if (this.GetHashCodeMethod == null) return 0;

      return this.GetHashCodeMethod(obj);
    }
  }  
}// class LambdaEqualityComparer

More advanced, to wrap GetHashCode into a projection (MiscUtil):
// -------------------------------------
// ProjectionEqualityComparer.cs
// -------------------------------------

namespace Common.Helpers
{
  using System;
  using System.Collections.Generic;

  /// <summary>
  /// Comparer uses projected keys from source element.
  /// </summary>
  /// Type of elements the comparer to project.
  /// Type of the key projected from the element.
  public class ProjectionEqualityComparer<TSource, TKey> : IEqualityComparer<TSource>
  {
    /// <summary>the comparison function.</summary>
    private readonly Func<TSource, TKey> projection;

    /// <summary>the equality comparer.</summary>
    private readonly IEqualityComparer<TKey> comparer;

    /// <summary>
    /// Initializes a new instance of the <see cref="ProjectionEqualityComparer{TSource, TKey}" />.
    /// Using default comparer for the projected type.
    /// </summary>
    public ProjectionEqualityComparer(
      Func<TSource, TKey> projection) : this(projection, null)
    {
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="ProjectionEqualityComparer{TSource, TKey}" />.
    /// The default comparer for the projected type is used if a comparer not specified.
    /// </summary>
    public ProjectionEqualityComparer(
      Func<TSource, TKey> projection, IEqualityComparer<TKey> comparer)
    {
      if (projection == null)
      {
        throw new ArgumentNullException("projection");
      }

      this.comparer = comparer ?? EqualityComparer<TKey>.Default;
      this.projection = projection;
    }

    /// <summary>
    /// Compares the two specified values for equality by applying the projection to
    /// each value and then using the equality comparer on the resulting keys.
    /// Null references are never passed to the projection.
    /// </summary>
    /// returns True if objects are equal; otherwise False.
    public bool Equals(TSource x, TSource y)
    {
      if (x == null && y == null) return true;
      if (x == null || y == null) return false;

      return this.comparer.Equals(this.projection(x), this.projection(y));
    }

    /// <summary>
    /// Produces a hash code for the given value by projecting it and then
    /// asking the equality comparer to find the hash code of the resulting key.
    /// </summary>
    /// returns the hash code.
    public int GetHashCode(TSource obj)
    {
      if (obj == null)
      {
        throw new ArgumentNullException("obj");
      }
      return this.comparer.GetHashCode(this.projection(obj));
    }
  }
}// class ProjectionEqualityComparer

Or using string value of a property name (see Cuemon.Reflection):
// -------------------------------------
// 
//  Copyleft (c) All rights released.
// 
// -------------------------------------

namespace Common.Helpers
{
  using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Reflection;

  /// <summary>
  /// Implements <see cref="IEqualityComparer{T}" /> interface.
  /// </summary>
  /// the type of an object.
  public class PropertyEqualityComparer<T> : IEqualityComparer<T>
  {
    /// <summary>the <see cref="PropertyInfo"/> object.</summary>
    private PropertyInfo propertyInfo;

    /// <summary>
    /// Initializes a new instance of the <see cref="PropertyEqualityComparer{T}" /> class.
    /// </summary>
    public PropertyEqualityComparer(string propertyName)
    {
      // store a reference to the <see cref="PropertyInfo"/> for use in comparison
      this.propertyInfo = typeof(T).GetProperty(
        propertyName, 
        BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.Public
        );
      if (this.propertyInfo == null)
      {
        var message = string.Format(
          "The name '{0}' is not a property of type {1}.", 
          propertyName, typeof(T));
        throw new ArgumentException(message);
      }
    }

    #region Methods :: Implments IEqualityComparer

    /// <summary>
    /// Implements Equals from <see cref="IEqualityComparer{T}" /> interface.
    /// </summary>
    /// returns result of the comparison.
    public bool Equals(T x, T y)
    {
      // get the current value of the comparison property of x and of y
      var valueX = this.propertyInfo.GetValue(x, null);
      var valueY = this.propertyInfo.GetValue(y, null);
    
      // consider equal only if both xValue and yValue are null
      if (valueX == null)
      {
        return valueY == null;
      }

      // use default comparer
      return valueX.Equals(valueY);
    }

    /// <summary>
    /// Implements GetHashCode from <see cref="IEqualityComparer{T}" /> interface.
    /// </summary>
    /// returns hash code.
    public int GetHashCode(T obj)
    {
      var propertyValue = this.propertyInfo.GetValue(obj, null);

      if (propertyValue != null)
      {
        return propertyValue.GetHashCode();
      }
      return 0;
    }
  
    #endregion
  }  
}

Happy coding!

Books on Tablet

今年继续『书香云集』的书目。目前国内的爱问资料新浪微盘可以下载许多书,却不能上传(不知何故)。

中文書目───
严歌苓: 《第九个寡妇》★★★《铁梨花》★★★
九鹭非香:《一时冲动,七世不祥》★★★
介 末: 《裸婚》》
何 伟: 《消失中的江城》
十四郎: 《怜香惜玉录》
吕 峥: 《明朝一哥王阳明》★★★★
唐七公子:《九州·华胥引》★★★★、《三生三世,十里桃花》★★★、《岁月是朵两生花》★★★
墨 武: 《纨绔才子》
天蚕土豆:《斗破苍穹》
小 春: 《不负如来不负卿》★★★
小号鲨鱼:《卜案:大唐李淳风传奇》★★★
小狐濡尾:《囚在湖中的大少爷》
尾 鱼: 《怨气撞铃》★★★
张小花: 《史上第一混乱》
张晚知: 《凤还巢》、《图南志》
当年明月:《明朝那些事儿》★★★★★
新垣平: 《剑桥倚天屠龙史》★★★★
易中天: 《品三国》、《大话方言》
曹 昇: 《嗜血的皇冠》★★★
李 可: 《杜拉拉升职记》★★★
桂 仁: 《逼草为妖》
桩 桩: 《皇后出墙记》
楼笙笙: 《别拿穿越不当工作》★★
沐 非: 《宸宫》★★★
流潋紫: 《后宫·甄嬛传》
海 宴: 《琅琊榜》★★★★
海 岩: 《作品集》★★★
潇湘冬儿:《十一处特工皇妃》
燕垒生: 《天行健》
猫 腻: 《间客》、《朱雀记》、《庆余年》★★★★
王 强: 《圈子圈套》★★★
罗大伦: 《古代的醫生》★★★★
老 夜: 《冒死记录中国神秘事件》
老 猪: 《紫川》
蘇 蘇: 《夙夜宫声》★★★★
蜀 客: 《王妃归来》★★★
袁腾飞: 《历史是什么玩意儿》
袖 唐: 《江山美人谋》★★★
转 身: 《凤栖宸宫》★★★
金 庸: 《书剑恩仇录》★★★
随波逐流:《一代军师》★★★★
雷 米: 《心理罪》★★★★
青 垚: 《天子谋(原名:苏记棺材铺)》★★★
风凝雪舞:《犹记惊鸿照影》、《亦筝笙》
高罗佩: 《狄公案》★★★★★
鲍鲸鲸: 《失恋33天》
鲜 橙: 《阿麦从军》★★★★★、《和亲公主》
黄晓阳: 《二号首长》、《印象中国:张艺谋传》
崔曼莉: 《浮沉》(1-3)★★★


★下载★天碟书架爱问资料新浪微盘微盘搜索百度云盘

猜字谜

★、山上还有山(出)
★、一个礼拜。(旨)
★、一人一张口,下面长只手。(拿)
★、一人在内。(肉)
★、一人腰上挂把弓。(夷)
★、一加一。(王)
★、一口吃掉牛尾巴。(告)
★、一口咬定。(交)
★、一只牛。(生)
★、一只狗,两个口,谁遇它谁发愁。(哭)
★、一只狗四个口。(器)
★、一只黑狗,不叫不吼(默)
★、一夜又一夜。(多)
★、一大二小。(奈)
★、一字十三点,难在如何点。(汁)
★、一家十一口。(吉)
★、一斗米。(料)
★、一月一日非今天。(明)
★、一月七日。(脂)
★、一点水准。(淮)
★、一百减一。(白)
★、一边是红,一边是绿,一边怕风,一边怕雨。(秋)
★、七人头上长了草。(花)
★、七十二小时。(晶)
★、三口重叠,莫把品字猜。(目)
★、三张纸。(顺)
★、上下串通、上下难分。(卡)
★、不要讲话。(吻)
★、九只鸟。(鸠)
★、九号。(旭)
★、九点。(丸)
★、九辆车。(轨)
★、互吻。(吕)
★、五十对耳朵。(陌)
★、五口之家,旁种一树。(梧)
★、人不在其位。(立)
★、人无信不立。(言)
★、人有他则变大。(一)
★、付出爱心。(受)
★、休要丢人现眼。(相)
★、兄有债。(歌)
★、八十八。(米)
★、公而忘私。(八)
★、六十不足,八十有余。(平)
★、刀出鞘。(力)
★、十一个读书人。(仕)
★、十个哥哥。(克)
★、十二点。(斗)
★、十张口,一颗心(思)
★、十日十月(武昌起义)。(朝)
★、千里丢一,百里丢一。(伯)
★、半个人。(伴)
★、半个月亮。(胖)
★、半真半假。(值)
★、半青半紫。(素)
★、反比。(北)
★、古时候的月亮。(胡)
★、四面都是山,山山都相连。(田)
★、多一半。(夕)
★、大丈夫不得出头。(天)
★、天上无二,合去一口,家家都有。(人)
★、天天。(晦)
★、太阳西边下,月儿东边挂。(明)
★、夫人何处去。(二)
★、如箭在弦。(引)
★、存心不让出大门,你说烦人不烦人。(闷)
★、守门员。(闪)
★、家中添一口。(豪)
★、小姑娘。(妙)
★、山上复山。(出)
★、左有十八,右有十八,二四得八,一八得八。(樊)
★、差一点六斤。(兵)
★、心如刀刺。(必)
★、手提包。(抱)
★、打断念头。(心)
★、文武两全。(斌)
★、日复一日。(昌)
★、旭日东升。(九)
★、有两个动物,一个在水里,一个在山上。(鲜)
★、有人偷车。(输)
★、有心得志。(士)
★、有目共睹。(者)
★、格外大方。(回)
★、正字少一横,不作止字猜。(步)
★、水上工程。(汞)
★、点点成金(全)
★、田中。(十)
★、皇帝新衣。(袭)
★、种花要除草,一人来一刀。(化)
★、综合门市。(闹)
★、自小在一起,目前少联系。(省)
★、说它小,下边大,说它大,上边小。(尖)
★、身残心不残。(息)
★、雨落在横山上。(雪)
★、雷不雨。(田)
★、需要一半,留下一半。(雷)

Fall colors on RedWest campus

Fall colors on RedWest campus Fall colors on RedWest campus

Fall colors on RedWest campus Fall colors on RedWest campus

Fall colors on RedWest campus Fall colors on RedWest campus

See more at PicasaWeb or Panoramio.


Fall Washington

Fall colors by Hwy 2, toward Leavenworth, WA Fall colors by Hwy 2, toward Leavenworth, WA





Algoryhme

I think that I shall never see
A graph more lovely than a tree.
A tree whose crucial property
Is loop-free connectivity.
A tree that must be sure to span
So packets can reach every LAN.
First, the root must be selected.
By ID, it is elected.
Least-cost paths from root are traced.
In the tree, these paths are placed.
A mesh is made by folks like me,
Then bridges find a spanning tree.

- an Algoryhme by Radia Perlman
(Developer of Spanning Tree, see also)

The Golf Club at Newcastle

The Golf Club At Newcastle, WA The Golf Club At Newcastle, WA
The Golf Club At Newcastle, WA The Golf Club At Newcastle, WA
Summer cloud, over Newcastle golf course
Summer cloud, over Newcastle golf course
Summer garden at Newcastle Golf Club Summer garden at Newcastle Golf Club

See more at PicasaWeb or Skydrive.

StartupCX

To improve customer experience, act like a startup:

  • Serve more than you sell;
  • Remember customers, not transactions;
  • Don't manage products, manage relationships;
  • Operate for the long run, not for today's closing stock price;
  • Do the right thing, even if no one is watching.
  • Be loyal to every employee who gives his or her all, especially when the economy gets tough.
  • Takers has done enough damage. Put givers in charge of customer experience.

See video: StartupCX - Andy A./PeoplePerHour