/// <summary>
        /// 判断用户是否有指定数据的所有权
        /// 如果部分数据不存在,会返回false
        /// </summary>
        /// <typeparam name="TData">数据类型</typeparam>
        /// <param name="userId">用户Id</param>
        /// <param name="ids">数据Id列表</param>
        /// <returns></returns>
        public virtual bool HasOwnership <TData>(long userId, IList <object> ids)
            where TData : class, IEntity
        {
            // 检查数据类型是否有所属用户
            var userOwnedTrait = UserOwnedTrait.For <TData>();

            if (!userOwnedTrait.IsUserOwned)
            {
                throw new ArgumentException(string.Format("type {0} not user owned", typeof(TData).Name));
            }
            // 构建表达式 (data => ids.Contains(data.Id) && data.Owner.Id == userId)
            var entityTrait     = EntityTrait.For <TData>();
            var userEntityTrait = EntityTrait.For <User>();
            var dataParam       = Expression.Parameter(typeof(TData), "data");
            var body            = Expression.AndAlso(
                Expression.Call(
                    IListContainsMethodInfo.Value,
                    Expression.Constant(ids.Select(id =>
                                                   id.ConvertOrDefault(entityTrait.PrimaryKeyType, null)).ToList()),
                    Expression.Convert(
                        Expression.Property(dataParam, entityTrait.PrimaryKey), typeof(object))),
                Expression.Equal(
                    Expression.Property(
                        Expression.Property(dataParam, userOwnedTrait.PropertyName),
                        userEntityTrait.PrimaryKey),
                    Expression.Constant(userId)));
            var count = UnitOfWork.ReadData <TData, long>(r => {
                return(r.Count(Expression.Lambda <Func <TData, bool> >(body, dataParam)));
            });

            return(count == ids.Count);
        }
        /// <summary>
        /// 按所属用户等于指定用户过滤数据
        /// </summary>
        /// <typeparam name="TData">数据类型</typeparam>
        /// <param name="query">查询对象</param>
        /// <param name="userId">用户Id</param>
        /// <returns></returns>
        public static IQueryable <TData> FilterByOwnedUser <TData>(
            this IQueryable <TData> query, long userId)
        {
            // 构建表达式 (data => data.Owner.Id == userId)
            var userOwnedTrait  = UserOwnedTrait.For <TData>();
            var userEntityTrait = EntityTrait.For <User>();
            var dataParam       = Expression.Parameter(typeof(TData), "data");
            var body            = Expression.Equal(
                Expression.Property(
                    Expression.Property(dataParam, userOwnedTrait.PropertyName),
                    userEntityTrait.PrimaryKey),
                Expression.Constant(userId));

            return(query.Where(Expression.Lambda <Func <TData, bool> >(body, dataParam)));
        }
        /// <summary>
        /// 设置数据的所属用户到当前登录用户
        /// </summary>
        /// <param name="context">数据库上下文</param>
        /// <param name="data">数据</param>
        protected virtual void AssignOwnedUser(IDatabaseContext context, TData data)
        {
            // 通过指定的数据库上下文获取当前登录用户
            var sessionManager = Application.Ioc.Resolve <SessionManager>();
            var session        = sessionManager.GetSession();
            var user           = context.Get <User>(u => u.Id == session.ReleatedId);

            if (user == null)
            {
                throw new NullReferenceException("Get user failed");
            }
            // 设置所属用户到当前登录用户
            var userOwnedTrait = UserOwnedTrait.For <TData>();

            if (!userOwnedTrait.IsUserOwned)
            {
                throw new ArgumentException(string.Format("type {0} not user owned", typeof(TData).Name));
            }
            ReflectionUtils.MakeSetter <TData, User>(userOwnedTrait.PropertyName)(data, user);
        }