具有存储过程的多租户EF实现

时间:2011-03-21 22:42:43

标签: c# entity-framework

问候!

我在Entity Framework中使用SPROC来获取所有CRUD方法。因为这是一个多租户数据库,所以我们在每个表中都有一个clientID字段。我们的DBA不希望暴露clientID,因此我们将用户名传递给SPROC(经过身份验证的用户的用户名,在成员资格提供程序中跟踪),然后在sproc内部处理用户名到clientID的转换。

我遇到的问题是我的实体没有Username属性。当我为insert / update / delete创建函数导入时,映射正在请求我的实体中不存在的用户名字段(必需来自我的SPROC)。这是我的架构:

帐户实体

账户号码
AccountDescription
客户端ID
ActiveFlag
RowVersion(用于并发)

我的SPROC:

ALTER PROCEDURE [dbo].[GetAccounts]
@Username   varchar (60)
AS

/*********************************************
Summary:  Get Accounts
2011-01-20 aca  initial version
2011-01-27 aca  Alias for Description
2011-03-21 aca  Implement user security
********************************************/
select  P.FERC_ACCOUNT,
    P.[DESCRIPTION] as AccountDescription,
    P.RowVersion
from    dbo.P_ACCOUNTS P
join    dbo.v_UserClient U
on  U.Username = @Username
and P.CLIENT_ID = U.Client_ID
where   P.ActiveFlag = 1;

RETURN 0;

我不确定最好的方法是什么。我只是在我的实体中创建一个Username属性吗?这意味着我必须在每个人身上做到这一点?我如何填充它?等等:)

感谢您的帮助!

斯科特

1 个答案:

答案 0 :(得分:1)

我有相同的限制,我将存储过程导出为函数。对于没有输出参数的过程,我返回默认生成的复杂类型,即GetAccountsResult。

public IEnumerable<GetAccountsResult> GetAccounts(string username)
{
    return ObjectContext.GetAccounts(username).AsQueryable();
}

复杂类型需要具有指定为[Key]的属性。要为complextypes设置密钥,我为域服务创建了一个部分,并使用buddy类来设置密钥。因此,对于AccountsDomainService.cs,我创建了AccountsDomainService.metadata.cs。

[MetadataType(typeof(GetAccountsResultMetadata))]
    public partial class GetAccountsResult
{
    internal sealed class GetAccountsResultMetadata
    {
        [Key]
        public int Id { get; set; }
    }
}

对于具有输出参数的过程,我创建一个包含输出参数属性的poco对象和另一个与复杂类型匹配的poco对象。然后我使用AutoMapper将返回的复杂类型映射到我创建的复杂类型。我这样做,所以我可以返回关系。

Account.cs

 public class Account
    {
        [Key]
        public int Id { get; set; }
        public string MyOutputParameter { get; set; }

        [Include, Association("Account_AccountDetails", "Id", "AccountId")]
        public List<AccountDetail> AccountDetails { get; set; }
    }

AccountDetail.cs

    public class AccountDetail
    {
        [Key]
        public int Id { get; set; }
        public int AccountId { get; set; }
        public string MyAccountDetailProperty { get; set; }
    }

AccountDomainService.cs

 public Account GetAccountsWithOutputParms(string username)
        {
            var myOutputParameter = new ObjectParameter("MyOutPutParameter", typeof(int));

            var tempGetAccountsResult = ObjectContext.GetAccounts(username).ToList();

            var account = new Account
                              {
                                  Id = 1,
                                  MyOutputParameter = myOutputParameter,
                                  AccountDetails = Mapper.Map<List<GetAccountsResult>, List<AccountDetail>>(tempGetAccountsResult)
                              };

            return accout;
        }

当我在客户端上获得这些结果时,我使用AutoMapper将它们映射到客户端视图模型。

This文章使用EF 4和RIA服务存储过程非常方便。

对于插入/更新,您可以创建一个poco对象,该对象为过程参数建模并将其传递给域服务中的导出函数。