仓储类型

  前一篇介绍了仓储的基本概念,并谈了我对仓储的一些认识,本文将实现仓储的基本功能。

  仓储代表聚合在内存中的集合,所以仓储的接口需要模拟得像一个集合。仓储中有很多操作都是可以通用的,可以把这部分操作抽取到基类中。

  在Util.Domains项目中创建一个文件夹Repositories,这个文件夹用来放仓储相关的接口。在Repositories下创建一个仓储接口IRepository

  把仓储基接口放到Util.Domains,是因为仓储接口是在领域层定义的,这与传统三层架构的数据访问层接口的位置不同。

  仓储是基础设施层的组成部分,位于领域层的下方,按理来说,领域层应该依赖仓储,但这会导致领域层与具体数据访问组件耦合,降低了领域层的复用能力。为了让领域层更加纯净,可以应用依赖倒置原则(DIP。依赖倒置原则提到,高层模块不应该依赖低层模块,这里的高层模块就是领域层,低层模块是基础设施层的仓储。

  依赖倒置原则反转了两者的依赖关系,即仓储反过来依赖于领域层。为了让领域层可以访问到仓储提供的服务,需要抽取仓储接口,你可以把这些接口放到独立的程序集中,但这会增加不必要的开销。一种更好的方法是直接把低层接口放入使用它们的客户程序集中,这样可以简化设计,仅在必要时才分离出独立的接口程序集。依赖倒置原则不仅适用于仓储,对于任何可能导致高耦合的基础设施服务都适用,比如第三方外部接口,发邮件,发短信等。

  在Util.Datas.Ef项目中创建一个仓储实现类Repository

  仓储接口IRepository的代码如下。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using Util.Datas;

namespace Util.Domains.Repositories {
    /// <summary>
    /// 仓储
    /// </summary>
    /// <typeparam name="TEntity">实体类型</typeparam>
    /// <typeparam name="TKey">实体标识类型</typeparam>
    public interface IRepository<TEntity, in TKey> where TEntity : class, IAggregateRoot<TKey> {
        /// <summary>
        /// 添加实体
        /// </summary>
        /// <param name="entity">实体</param>
        void Add( TEntity entity );
        /// <summary>
        /// 添加实体
        /// </summary>
        /// <param name="entities">实体</param>
        void Add( IEnumerable<TEntity> entities );
        /// <summary>
        /// 修改实体
        /// </summary>
        /// <param name="entity">实体</param>
        void Update( TEntity entity );
        /// <summary>
        /// 移除实体
        /// </summary>
        /// <param name="id">实体标识</param>
        void Remove( TKey id );
        /// <summary>
        /// 移除实体
        /// </summary>
        /// <param name="entity">实体</param>
        void Remove( TEntity entity );
        /// <summary>
        /// 查找实体集合
        /// </summary>
        List<TEntity> FindAll();
        /// <summary>
        /// 查找实体集合
        /// </summary>
        IQueryable<TEntity> Find();
        /// <summary>
        /// 查找实体
        /// </summary>
        /// <param name="id">实体标识</param>
        TEntity Find( params object[] id );
        /// <summary>
        /// 查找实体列表
        /// </summary>
        /// <param name="ids">实体标识列表</param>
        List<TEntity> Find( IEnumerable<TKey> ids );
        /// <summary>
        /// 判断实体是否存在
        /// </summary>
        /// <param name="predicate">条件</param>
        bool Exists( Expression<Func<TEntity, bool>> predicate );
        /// <summary>
        /// 索引器查找,获取指定标识的实体
        /// </summary>
        /// <param name="id">实体标识</param>
        TEntity this[TKey id] { get; }
        /// <summary>
        /// 保存
        /// </summary>
        void Save();
        /// <summary>
        /// 获取工作单元
        /// </summary>
        IUnitOfWork GetUnitOfWork();
    }
}

using System;

namespace Util.Domains.Repositories {
    /// <summary>
    /// 仓储
    /// </summary>
    /// <typeparam name="TEntity">实体类型</typeparam>
    public interface IRepository<TEntity> : IRepository<TEntity, Guid> where TEntity : class, IAggregateRoot<Guid> {
    }
}

  仓储实现类Repository的代码如下。

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using Util.Domains;
using Util.Domains.Repositories;

namespace Util.Datas.Ef {
    /// <summary>
    /// 仓储
    /// </summary>
    /// <typeparam name="TEntity">实体类型</typeparam>
    /// <typeparam name="TKey">实体标识类型</typeparam>
    public abstract class Repository<TEntity, TKey> : IRepository<TEntity, TKey> where TEntity : class, IAggregateRoot<TKey> {
        /// <summary>
        /// 初始化仓储
        /// </summary>
        /// <param name="unitOfWork">工作单元</param>
        protected Repository( IUnitOfWork unitOfWork ) {
            UnitOfWork = (EfUnitOfWork)unitOfWork;
        }

        /// <summary>
        /// Ef工作单元
        /// </summary>
        protected EfUnitOfWork UnitOfWork { get; private set; }

        /// <summary>
        /// 添加实体
        /// </summary>
        /// <param name="entity">实体</param>
        public void Add( TEntity entity ) {
            UnitOfWork.Set<TEntity>().Add( entity );
            UnitOfWork.CommitByStart();
        }

        /// <summary>
        /// 添加实体
        /// </summary>
        /// <param name="entities">实体</param>
        public void Add( IEnumerable<TEntity> entities ) {
            if ( entities == null )
                return;
            UnitOfWork.Set<TEntity>().AddRange( entities );
            UnitOfWork.CommitByStart();
        }

        /// <summary>
        /// 修改实体
        /// </summary>
        /// <param name="entity">实体</param>
        public virtual void Update( TEntity entity ) {
            UnitOfWork.Entry( entity ).State = EntityState.Modified;
            UnitOfWork.CommitByStart();
        }

        /// <summary>
        /// 移除实体
        /// </summary>
        /// <param name="id">实体标识</param>
        public void Remove( TKey id ) {
            var entity = Find( id );
            if ( entity == null )
                return;
            Remove( entity );
        }

        /// <summary>
        /// 移除实体
        /// </summary>
        /// <param name="entity">实体</param>
        public void Remove( TEntity entity ) {
            UnitOfWork.Set<TEntity>().Remove( entity );
            UnitOfWork.CommitByStart();
        }

        /// <summary>
        /// 查找实体集合
        /// </summary>
        public List<TEntity> FindAll() {
            return Find().ToList();
        }

        /// <summary>
        /// 查找实体
        /// </summary>
        public IQueryable<TEntity> Find() {
            return UnitOfWork.Set<TEntity>();
        }

        /// <summary>
        /// 查找实体
        /// </summary>
        /// <param name="id">实体标识</param>
        public TEntity Find( params object[] id ) {
            return UnitOfWork.Set<TEntity>().Find( id );
        }

        /// <summary>
        /// 查找实体列表
        /// </summary>
        /// <param name="ids">实体标识列表</param>
        public List<TEntity> Find( IEnumerable<TKey> ids ) {
            if ( ids == null )
                return null;
            return Find().Where( t => ids.Contains( t.Id ) ).ToList();
        }

        /// <summary>
        /// 索引器查找,获取指定标识的实体
        /// </summary>
        /// <param name="id">实体标识</param>
        public TEntity this[TKey id] {
            get { return Find( id ); }
        }

        /// <summary>
        /// 判断实体是否存在
        /// </summary>
        /// <param name="predicate">条件</param>
        public bool Exists( Expression<Func<TEntity, bool>> predicate ) {
            return Find().Any( predicate );
        }

        /// <summary>
        /// 保存
        /// </summary>
        public void Save() {
            UnitOfWork.Commit();
        }

        /// <summary>
        /// 获取工作单元
        /// </summary>
        public IUnitOfWork GetUnitOfWork() {
            return UnitOfWork;
        }
    }
}

using System;
using Util.Domains;

namespace Util.Datas.Ef {
    /// <summary>
    /// 仓储
    /// </summary>
    /// <typeparam name="TEntity">实体类型</typeparam>
    public abstract class Repository<TEntity> : Repository<TEntity, Guid> where TEntity : class, IAggregateRoot<Guid> {
        /// <summary>
        /// 初始化仓储
        /// </summary>
        /// <param name="unitOfWork">工作单元</param>
        protected Repository( IUnitOfWork unitOfWork )
            : base( unitOfWork ) {
        }
    }
}

  仓储是对聚合的操作,所以泛型接口声明IRepository<TEntity, in TKey> where TEntity : class, IAggregateRoot<TKey>对TEntity类型限定为聚合。

  在Repository实现类中,通过注入DbContext工作单元来完成所有的工作。IUnitOfWorkEfUnitOfWork是在应用程序框架实战十九:工作单元层超类型中定义的,EfUnitOfWork从DbContext派生,它有一个核心方法CommitByStart,用来告诉仓储,如果开启了工作单元就等待调用端通过Commit提交,否则立即提交。每个数据更新方法Add、Update、Remove都会调用CommitByStart方法。

  对于使用Entity Framework 进行Update修改操作有多种实现方式。在仓储基类中实现的Update方法比较通用,但我手工编写代码时一般会直接把聚合取出来,修改聚合属性,再提交工作单元。

  本文介绍了仓储通用操作的基本实现,后续文章我将介绍如何通过表达式树对查询扩展和封装。

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using Webdiyer.WebControls.Mvc;
using System.Text;
using BExpress.Model;

namespace BExpress.DAL.Repositories
{
using System.Data.Entity.Validation;

/// <summary>
/// 通用仓储实现类
/// </summary>
/// <typeparam name="TEntity"><see cref="T:System.Data.Entity.DbSet`1"/></typeparam>
public class GenericRepository<TEntity> where TEntity : class
{
public BExpressDbContext context;
public DbSet<TEntity> dbSet;
/// <summary>
/// 实例化一个仓储基类实现
/// </summary>
/// <param name="context">EF 上下文</param>
public GenericRepository(BExpressDbContext context)
{
this.context = context;
this.dbSet = context.Set<TEntity>();
}
/// <summary>
/// 根据查询条件或排序规则获得实体集合
/// </summary>
/// <param name="filter">过滤条件</param>
/// <param name="orderBy">排序规则</param>
/// <param name="includeProperties">包含的外键属性名</param>
/// <returns></returns>
public virtual IEnumerable<TEntity> Get(
Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
string includeProperties = "")
{
IQueryable<TEntity> query = dbSet;
if (filter != null)
{
query = query.Where(filter);
}

query = includeProperties.Split(new[] {‘,‘}, StringSplitOptions.RemoveEmptyEntries).Aggregate(query, (current, includeProperty) => current.Include(includeProperty));

return orderBy != null ? orderBy(query).ToList() : query.ToList();
}
/// <summary>
/// 获取一个包装成<see cref="T:Webdiyer.WebControls.Mvc.PagedList`1"/>的实体集合
/// </summary>
/// <param name="filter">过滤条件</param>
/// <param name="orderBy">排序规则</param>
/// <param name="includeProperties">包含的外键属性名</param>
/// <param name="pageIndex">页索引</param>
/// <param name="pageSize">页大小</param>
/// <returns></returns>
public virtual PagedList<TEntity> GetPaging(Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy,
Expression<Func<TEntity, bool>> filter = null,
string includeProperties = "", int pageIndex = 1, int pageSize = 20)
{
IQueryable<TEntity> query = dbSet;
if (filter != null)
{
query = query.Where(filter);
}

query = includeProperties.Split(new[] {‘,‘}, StringSplitOptions.RemoveEmptyEntries).Aggregate(query, (current, includeProperty) => current.Include(includeProperty));
var list = orderBy(query).Skip((pageIndex - 1) * pageSize).Take(pageSize).AsEnumerable();
var count = 0;
count = filter == null ? dbSet.Count() : dbSet.Count(filter);
return new PagedList<TEntity>(list, pageIndex, pageSize, count);
}
/// <summary>
/// 根据查询条件或排序规则获得单个实体
/// </summary>
/// <param name="filter">过滤条件</param>
/// <param name="orderBy">排序规则</param>
/// <param name="includeProperties">包含的外键属性名</param>
/// <param name="isAttach">是否附加到DbContext上下文进行跟踪</param>
/// <returns></returns>
public virtual TEntity GetFirst(Expression<Func<TEntity, bool>> filter = null, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
string includeProperties = "", bool isAttach = true)
{
IQueryable<TEntity> query = dbSet;
if (filter != null)
{
query = query.Where(filter);
}

query = includeProperties.Split(new[] {‘,‘}, StringSplitOptions.RemoveEmptyEntries).Aggregate(query, (current, includeProperty) => current.Include(includeProperty));

//if (orderBy != null)
//{
// return isAttach ? orderBy(query).FirstOrDefault() : orderBy(query).AsNoTracking().FirstOrDefault();
//}
return isAttach ? query.FirstOrDefault() : query.AsNoTracking().FirstOrDefault();
}
/// <summary>
/// 根据主键Id获取单个实体对象
/// </summary>
/// <param name="id">id,通常是主键</param>
public virtual TEntity GetByID(object id)
{
return dbSet.Find(id);
}
/// <summary>
/// 获取单个(不会被跟踪)实体
/// </summary>
/// <param name="pred">条件谓词</param>
/// <returns><see cref="TEntity"/></returns>
public virtual TEntity SingleOrDefault(Func<TEntity, bool> pred)
{
var obj = dbSet.AsNoTracking().SingleOrDefault(pred);
return obj;
}
/// <summary>
/// 插入一个实体对象
/// <para>需手动调用Save方法</para>
/// </summary>
/// <param name="entity">实体对象</param>
/// <returns></returns>
public virtual TEntity Insert(TEntity entity)
{
return dbSet.Add(entity);
}
/// <summary>
/// 根据实体主键删除实体对象
/// <para>需手动调用Save方法</para>
/// </summary>
/// <param name="id">通常是主键id</param>
public virtual void Delete(object id)
{
TEntity entityToDelete = dbSet.Find(id);
Delete(entityToDelete);
}

/// <summary>
/// 根据主键Id集合批量删除实体
/// <para>需手动调用Save方法</para>
/// </summary>
/// <param name="ids"></param>
public virtual void DeleteMultiple(IEnumerable<int> ids)
{
if (ids == null) return;
foreach (TEntity entityToDelete in ids.Select(id => dbSet.Find(id)))
{
if (entityToDelete == null)
{
continue;
}
Delete(entityToDelete);
}
}
/// <summary>
/// 删除单个实体
/// <para>需手动调用Save方法</para>
/// </summary>
/// <param name="entityToDelete">要删除的实体对象</param>
public virtual void Delete(TEntity entityToDelete)
{
if (context.Entry(entityToDelete).State == EntityState.Detached)
{
dbSet.Attach(entityToDelete);
}
dbSet.Remove(entityToDelete);
}
/// <summary>
/// 更新一个实体
/// <para>需手动调用Save方法</para>
/// </summary>
/// <param name="entityToUpdate">要被更新的实体对象</param>
public virtual void Update(TEntity entityToUpdate)
{
//dbSet.Attach(entityToUpdate);
if (context.Entry(entityToUpdate).State == EntityState.Detached)
{
dbSet.Attach(entityToUpdate);
}
context.Entry(entityToUpdate).State = EntityState.Modified;
}
/// <summary>
/// 根据原生SQL语句查询<see cref="TEntity"/>实体集合
/// </summary>
/// <param name="query">SQL语句</param>
/// <param name="parameters">参数</param>
/// <returns></returns>
public virtual IEnumerable<TEntity> GetWithRawSql(string query, params object[] parameters)
{
return dbSet.SqlQuery(query, parameters).ToList();
}
/// <summary>
/// 根据条件获得实体对象的数量
/// </summary>
/// <param name="filter">过滤条件</param>
/// <returns></returns>
public virtual int Count(Expression<Func<TEntity, bool>> filter = null)
{
return filter != null ? dbSet.Count(filter) : dbSet.Count();
}

#region AddTime:20140821 11:30 By:Ax0ne
/// <summary>
/// 获取实体中单个属性值
/// </summary>
/// <typeparam name="T">返回值的类型</typeparam>
/// <param name="selector">返回哪个属性值</param>
/// <param name="predicate">条件</param>
/// <returns></returns>
public virtual T GetField<T>(Expression<Func<TEntity, T>> selector, Expression<Func<TEntity, bool>> predicate, string includeProperties = "")
{
IQueryable<TEntity> query = dbSet;
if (!string.IsNullOrWhiteSpace(includeProperties))
{
query = includeProperties.Split(new[] { ‘,‘ }, StringSplitOptions.RemoveEmptyEntries).Aggregate(query, (current, includeProperty) => current.Include(includeProperty));
}
return query.Where(predicate).Select(selector).FirstOrDefault();
}
/// <summary>
/// 获取实体中单个属性值
/// <para>返回Ienumerable,可以直接把返回结果写在下条查询里,这样原本两条查询就变成一条.ToList或遍历就可以立即查询</para>
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="selector"></param>
/// <param name="predicate"></param>
/// <returns></returns>
public virtual IEnumerable<T> GetFields<T>(Expression<Func<TEntity, T>> selector, Expression<Func<TEntity, bool>> predicate)
{
// AddTime:20141112 14:05 by:Ax0ne
return dbSet.Where(predicate).Select(selector).AsEnumerable();
}

/// <summary>
/// 判断实体对象是否存在
/// </summary>
/// <param name="filter">条件</param>
/// <returns></returns>
public virtual bool IsExist(Expression<Func<TEntity, bool>> filter)
{
return Count(filter) > 0;
}
#region AddTime:20150123 17:00

private int Add(TEntity instance, bool isSave = true, bool attach = true)
{
if (attach)
{
this.dbSet.Attach(instance);
}
this.context.Entry(instance).State = EntityState.Added;
if (isSave)
{
return Save();
}
else
{
return 0;
}
}
/// <summary>
/// 批量添加实体对象
/// </summary>
/// <param name="entities">实体对象集合</param>
/// <param name="isSave">是否保存</param>
/// <returns></returns>
public int AddBatch(IEnumerable<TEntity> entities, bool isSave = true)
{
return InnerOperator(entities, o => Add(o, false), isSave);
}

private int InnerOperator(IEnumerable<TEntity> entities, Func<TEntity, int> method, bool isSave)
{
// 方法的封装
// AddTime:20141011 11:50
int result = 0;
foreach (var item in entities)
{
method(item);
}
if (isSave)
{
this.context.Configuration.AutoDetectChangesEnabled = false;
this.context.Configuration.ValidateOnSaveEnabled = false;
try
{
result = Save();
}
finally
{
this.context.Configuration.AutoDetectChangesEnabled = true;
this.context.Configuration.ValidateOnSaveEnabled = true;
}
}
return result;
}
/// <summary>
/// 批量更新实体对象
/// </summary>
/// <param name="entities">实体对象集合</param>
/// <param name="isSave">是否保存</param>
/// <returns></returns>
public int UpdateBatch(IEnumerable<TEntity> entities, bool isSave = true)
{
return InnerOperator(entities, o => Update(o, false), isSave);
}

private int Update(TEntity instance, bool isSave = true, bool attach = true)
{
if (attach)
{
this.dbSet.Attach(instance);
}
this.context.Entry(instance).State = EntityState.Modified;
if (isSave)
{
return Save();
}
else
{
return 0;
}
}
private int Save()
{
int result = 0;
try
{
result = context.SaveChanges();
}
catch (Exception exception)
{
Exception ex = exception;
while (ex.InnerException != null)
{
ex = ex.InnerException;
}
var entityException = ex as DbEntityValidationException;
if (entityException != null)
{
foreach (var errs in entityException.EntityValidationErrors)
{
foreach (var err in errs.ValidationErrors)
{
string exMessage = string.Format("\r\n属性[ {0} ] 的异常信息--->>>{1}", err.PropertyName, err.ErrorMessage);
System.Diagnostics.Trace.TraceError(exMessage);
throw new DbEntityValidationException(exMessage);
}
}
}
throw new Exception(ex.Message);
}
return result;
}
#endregion
/// <summary>
/// 执行DML语句 多条用 ; 结尾
/// </summary>
/// <param name="sqlText"></param>
/// <returns></returns>
public bool ExecuteSqlCommand(string sqlText)
{
if (string.IsNullOrWhiteSpace(sqlText)) return false;
context.Database.CommandTimeout = 120;
return context.Database.ExecuteSqlCommand(sqlText) > 0;
}
/// <summary>
/// 参数化执行DML语句 多条用 ; 结尾
/// </summary>
/// <param name="sqlText"></param>
/// <param name="parameters"></param>
/// <returns></returns>
public bool ExecuteSqlCommand(string sqlText, params object[] parameters)
{
if (string.IsNullOrWhiteSpace(sqlText)) return false;
return context.Database.ExecuteSqlCommand(sqlText, parameters) > 0;
}
#endregion
}
}

原文地址:https://www.cnblogs.com/w2017/p/8280123.html

时间: 2024-11-23 20:07:39

仓储类型的相关文章

.NET MVC4 实训记录之四(Unit of work + Repository)

今日后开启进阶模式! 谈到MVC与EntityFramework,则不得不说一说事务与仓储(Unit of work + Repository). 仓储(Repository):领域对象集合.用于操作领域对象与数据库上下文(DbContext)的交互(在此不得不说一声,领域对象和数据库表对象还是有区别的.领域对象实际上是一组有业务关系的数据库对象的抽象.最简单的形式就是主表.关系表在同一个领域对象中进行定义.例如我们前几章看到的UserProfile,它即定义了用户信息,又定义了用户角色关系信息

SAP 常用业务数据表设计

表的要求表中使用的字段请尽量参照各模块的SAP字段标准使用习惯:  例:"ZXSLRZX销售组织对应的利润中心"中的销售组织应该使用VKORG.利润中心应该使用PRCTR.根据表的用途,需确定是否属于配置目的.还是业务目的.配置表的建议:需要加入MANDT字段  例: "ZQJQD缺件清单"就没有MANDT字段需提供相应的维护视图:例:如ZCHECK_MM01工厂和利润中心的对应为保证DEV/QAS/PRD系统的一致性,不应该对配置表提供批量维护的功能,而应该走Re

设计窘境:来自 Repository 的一丝线索,Domain Model 再重新设计

写在前面 阅读目录: 疑惑解读 设计窘境 一幅图的灵感 为嘛还是你-Repository 后记 上一篇<No zuo no die:DDD 应对具体业务场景,Domain Model 重新设计>. 希望本篇博文废话少点,注:上一篇瞎扯的地方太多. 疑惑解读 先回顾一下,在上一篇博文中,主要阐述的是领域模型的重新设计,包含:真正的去理解领域模型和领域服务的加入(感兴趣的朋友可以看下前几篇来了解一下前因后果.).凡事都有修改的理由,为什么加入领域服务,主要是之前对领域模型的认知不够(实体充当起了伪

iOS---数据本地化

本篇随笔除了介绍 iOS 数据持久化知识之外,还贯穿了以下内容: (1)自定义 TableView,结合 block 从 ViewController 中分离出 View,轻 ViewController 的实现,提高 TableView 的复用性 (2)Model「实体层」+View「视图层」+ViewController「视图控制器层」+Service「服务层」+Database「数据库层」,MVC 多层架构的实现 (3)TableView 单元格滑动手势控制显示实用按钮,实用按钮为「修改」

SAP问题【转载】

1.A:在公司代码分配折旧表时报错? 在公司代码分配折旧表时报错,提示是"3000 的公司代码分录不完全-参见长文本" 希望各位大侠帮我看看. 3000 的公司代码分录不完全-参见长文本 R: a.你把零进项税的代码分配给这个公司代码就可以了 .没有指定非税代码,OBCL b.据此可能company code 设置有问题,检查一下OBY6 2.a,维护客户科目组:财政供应链管理->现金和流转情况管理->现金管理->主数据->子分类帐科目->客户控制->

SAP错误问题汇总

1.A:在公司代码分配折旧表时报错? 在公司代码分配折旧表时报错,提示是"3000 的公司代码分录不完全-参见长文本" 希望各位大侠帮我看看. 3000 的公司代码分录不完全-参见长文本 R: a.你把零进项税的代码分配给这个公司代码就可以了 .没有指定非税代码,OBCL b.据此可能company code 设置有问题,检查一下OBY6 2.a,维护客户科目组:财政供应链管理->现金和流转情况管理->现金管理->主数据->子分类帐科目->客户控制->

Contoso 大学 - 10 - 高级 EF 应用场景

原文地址:http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/advanced-entity-framework-scenarios-for-an-mvc-web-application全文目录:Contoso 大学 - 使用 EF Code First 创建 MVC 应用 在上一个教程中,你已经实现了仓储和工作单元模式.这个教程涵盖下列主题: 执行原始的 SQL 查询 执行没有跟踪的查询 检查发送到数据库的查询

sapwm培训

WM仓库管理是SAP系统中的后勤模块.该模块以仓库管理为核心,完成物料在仓库记忆仓库与外界之间的移动及方位.早期SAP系统版本中,WM模块属于MM物料管理模块中的一部分,从4.5版本开始,WM开始单独出来作为一个子模块.具体我们从该模块的系统结构跟库存管理(Inventory Management,简称IM.),对比认识. (更多信息百度:51sap实战中心) IM在是库存地点(Storage Location,也有人叫它仓库,为了跟WM的仓库区分,这里统一用库存地点来称呼)级别上进行物料数量级

SAPWM

WM仓库管理是SAP系统中的后勤模块.该模块以仓库管理为核心,完成物料在仓库记忆仓库与外界之间的移动及方位.早期SAP系统版本中,WM模块属于MM物料管理模块中的一部分,从4.5版本开始,WM开始单独出来作为一个子模块.具体我们从该模块的系统结构跟库存管理(Inventory Management,简称IM.),对比认识. (更多信息百度:51sap实战中心) IM在是库存地点(Storage Location,也有人叫它仓库,为了跟WM的仓库区分,这里统一用库存地点来称呼)级别上进行物料数量级