ASP.NET Web应用程序中数据映射器的存储

ASP.NET Web应用程序中数据映射器的存储,asp.net,database,datamapper,poeaa,identity-map,Asp.net,Database,Datamapper,Poeaa,Identity Map,在Martin Fowler的“企业应用程序架构模式”中 描述了将DAL组织为一组实体映射器的方法。每个都有自己的标识映射存储特定的实体 例如,在我的ASP.NET Web应用程序中: //AbstractMapper - superclass for all mappers in DAL public abstract class AbstractMapper { private readonly string _connectionString; protected stri

在Martin Fowler的“企业应用程序架构模式”中 描述了将DAL组织为一组实体映射器的方法。每个都有自己的标识映射存储特定的实体

例如,在我的ASP.NET Web应用程序中:

//AbstractMapper - superclass for all mappers in DAL
public abstract class AbstractMapper
{
    private readonly string _connectionString;
    protected string ConnectionString
    {
      get { return _connectionString; }  
    }

    private readonly DbProviderFactory _dbFactory;
    protected DbProviderFactory DBFactory
    {
        get { return _dbFactory; }
    } 

    #region LoadedObjects (IdentityMap)
    protected Hashtable LoadedObjects = new Hashtable();

    public void RegisterObject(long id, DomainObject obj)
    {
        LoadedObjects[id] = obj;            
    }

    public void UnregisterObject(long id)
    {
        LoadedObjects.Remove(id);
    }
    #endregion

    public AbstractMapper(string connectionString, DbProviderFactory dbFactory)
    {
        _connectionString = connectionString;
        _dbFactory = dbFactory;
    }

    protected virtual string DBTable
    {
        get
        {
            throw new NotImplementedException("database table is not defined in class " + this.GetType()); 
        }
    }

    protected virtual T Find<T>(long id, IDbTransaction tr = null) where T : DomainObject
    {
        if (id == 0)
            return null;
        T result = (T)LoadedObjects[id];
        if (result != null)
            return result;
        IDbConnection cn = GetConnection(tr);
        IDbCommand cmd = CreateCommand(GetFindStatement(id), cn, tr);
        IDataReader rs = null;
        try
        {
            OpenConnection(cn, tr);
            rs = cmd.ExecuteReader(CommandBehavior.SingleRow);
            result = (rs.Read()) ? Load<T>(rs) : null;                  
        }
        catch (DbException ex)
        {
            throw new DALException("Error while loading an object by id in class " + this.GetType(), ex);
        }
        finally
        {
            CleanUpDBResources(cmd, cn, tr, rs);
        }
        return result;
    }

    protected virtual T Load<T>(IDataReader rs) where T : DomainObject
    {
        long id = GetReaderLong(rs["ID"]);
        T result = (T)LoadedObjects[id];
        if (result != null) 
            return result;

        result = (T)DoLoad(id, rs);
        RegisterObject(id, result);
        return result;
    }

    // another CRUD here ...
}

// Specific Mapper for entity Account
public class AccountMapper : AbstractMapper
{
internal override string DBTable
{
    get { return "Account"; }
}

public AccountMapper(string connectionString, DbProviderFactory dbFactory) : base(connectionString, dbFactory) { }

public Account Find(long id)
{
    return Find<Account>(id);
}

public override DomainObject DoLoad(long id, IDataReader rs)
{
    Account account = new Account(id);
    account.Name = GetReaderString(rs["Name"]);
    account.Value = GetReaderDecimal(rs["Value"]);
    account.CurrencyID = GetReaderLong(rs["CurrencyID"]);
    return account;
}

// ...
但是在哪里可以存储MapperRegistry实例?我看到以下变体,但不喜欢其中任何一个:

  • MapperRegistry是全局应用程序(单例)

    • 不适用,因为在多线程ASP.NET应用程序中需要同步(至少Martin说只有mad可以选择此变体)
  • 每个会话的MapperRegistry

    • 看起来也不太好。所有ORM(NHibernate、LINQ to SQL、EntityFramework)主控程序都建议每个请求使用DataContext(NHibernateSession、ObjectContext),而不要在会话中存储上下文
    • 在我的WebApp中,几乎所有请求都是对EntityController.asmx(带有属性ScriptService)的AJAX请求,返回JSON。和会话是不允许的
  • 每个请求的MapperRegistry

    • 有很多单独的AJAX调用。在这种情况下,MapperRegistry的生命周期将太小。因此,数据几乎总是从数据库中检索,结果导致性能低下

  • 亲爱的专家们,请帮助我解决架构问题

    有什么原因不能使用ORM框架吗?如果基本上只需要反映数据库方案的映射,那么有一些轻量级的映射。一个轻量级的很简单。不幸的是,是的。系统的主要部分已经编写和测试。它甚至在使用,但不是那么积极。不久,用户数量将增加,这引起了对性能和通用架构正确性的担忧。希望有更少耗时的解决方案。。。
        public class AccountService : DomainService
    {
        public static Account FindAccount(long accountID)
        {
            if (accountID > 0)
                return MapperRegistry.AccountMapper.Find(accountID);
            return null;
        }
        ...
    }