简体   繁体   English

带存储过程的多租户EF实施

[英]Multi tenant EF implementation w/ Stored Procedures

Greetings! 问候!

I'm using SPROCs within Entity Framework for all of my CRUD methods. 我在所有CRUD方法的实体框架中都使用了SPROC。 Because this is a multi-tenant database, we have a clientID field in each of the tables. 因为这是一个多租户数据库,所以在每个表中都有一个clientID字段。 Our DBA doesn't want that clientID exposed, so we pass a username into the SPROC (username of authenticated user, tracked in the membership provider), which then handles conversion of username to clientID internally within sproc. 我们的DBA不想公开该clientID,因此我们将一个用户名传递给SPROC(经过身份验证的用户的用户名,在成员资格提供程序中进行跟踪),该程序然后在sproc内部处理用户名到clientID的转换。

The issue I'm having is that my Entities don't have the Username property. 我遇到的问题是我的实体没有Username属性。 When I create my function imports for insert/update/delete, the mapping is requesting a Username field (required, from my SPROC) which doesn't exist in my entity. 当我创建用于插入/更新/删除的函数导入时,映射请求的是用户名字段(从我的SPROC那里是必需的),该字段在我的实体中不存在。 Here's my schema: 这是我的架构:

Account Entity 帐户实体

AccountNumber 帐号
AccountDescription AccountDescription
ClientID 客户端ID
ActiveFlag ActiveFlag
RowVersion (for concurrency) RowVersion(用于并发)

And my SPROC: 而我的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;

I'm not sure what the best way to proceed is. 我不确定最好的处理方法是什么。 Do I just create a Username property in my entity? 我是否仅在实体中创建Username属性? That means I'd have to do this on every one? 这意味着我必须对每个人都这样做吗? How do I populate it? 如何填充? Etc etc :) 等等等:)

Thanks for your help! 谢谢你的帮助!

Scott 斯科特

I have the same restrictions and I export the stored procedures as functions. 我有相同的限制,并且将存储过程导出为函数。 For procedures that do not have output parameters I return the default generated complex type ie GetAccountsResult. 对于没有输出参数的过程,我返回默认的生成的复杂类型,即GetAccountsResult。

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

The complex type needs to have a property designated as the [Key]. 复杂类型需要具有一个指定为[Key]的属性。 To set the key for complextypes I create a partial for my domain service and use a buddy class to set the key. 要为复杂类型设置密钥,我为我的域服务创建了部分密钥,并使用了一个伙伴类来设置密钥。 So for AccountsDomainService.cs I create AccountsDomainService.metadata.cs. 因此,对于AccountsDomainService.cs,我创建了AccountsDomainService.metadata.cs。

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

For procedures that do have output parameters I create a poco object containing properties for the output parameters and another poco object matching the complex type. 对于确实具有输出参数的过程,我创建了一个poco对象,其中包含输出参数的属性以及另一个与复杂类型匹配的poco对象。 I then use AutoMapper to map the returned complex type to my created complex type. 然后,我使用AutoMapper将返回的复杂类型映射到我创建的复杂类型。 I do this so I can return the relation. 我这样做是为了返回关系。

Account.cs 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 AccountDetail.cs

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

AccountDomainService.cs 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;
        }

When I get those results on the client, I use AutoMapper to map them to client side view models. 当在客户端上获得这些结果时,我将使用AutoMapper将其映射到客户端视图模型。

This article Stored Procedures with EF 4 and RIA Services is handy. 文章与存储EF 4程序和RIA Services是得心应手。

For insert/update you can create a poco object that models the procedure parameters and pass it to your exported function in your domain service. 对于插入/更新,您可以创建一个对过程参数建模的poco对象,并将其传递给域服务中的导出函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM