在现有Entity Framework数据库中使用SqlProvider表及连接字符串问题
我来帮你搞定这个问题——你碰到的核心矛盾其实很清楚:Entity Framework需要带metadata的实体连接字符串,但ASP.NET Membership的SqlProvider只认纯ADO.NET连接字符串,直接混用肯定会炸出那个Keyword not supported: 'metadata'的错误。下面一步步给你解决:
别晕,其实就是两种不同的用途:
- EF实体连接字符串:包含了EF模型的元数据信息(.csdl/.ssdl/.msl文件),用来告诉EF怎么映射你的实体和数据库表,格式长这样:
metadata=res://*/YourModel.csdl|res://*/YourModel.ssdl|res://*/YourModel.msl;provider=System.Data.SqlClient;provider connection string="..." - ADO.NET连接字符串:就是直接连数据库的纯字符串,没有额外的EF元数据,SqlProvider(Membership)只认这种,格式是:
Data Source=你的服务器;Initial Catalog=你的数据库名;Integrated Security=True;
你不需要把它们揉成一个,而是在配置文件里分开配置,然后让EF和Membership各用各的就好:
第一步:在配置文件里添加两个连接字符串
打开你的Web.config(Web项目)或者App.config(桌面项目),找到<connectionStrings>节点,添加这两个配置:
<connectionStrings> <!-- 给EF用的实体连接字符串 --> <add name="YourEFContext" connectionString="metadata=res://*/YourModel.csdl|res://*/YourModel.ssdl|res://*/YourModel.msl;provider=System.Data.SqlClient;provider connection string="Data Source=.;Initial Catalog=YourDB;Integrated Security=True;MultipleActiveResultSets=True"" providerName="System.Data.EntityClient" /> <!-- 给Membership(SqlProvider)用的纯ADO连接字符串 --> <add name="MembershipConn" connectionString="Data Source=.;Initial Catalog=YourDB;Integrated Security=True;" providerName="System.Data.SqlClient" /> </connectionStrings>
注意两个连接字符串指向的是同一个数据库,这样Membership创建的用户数据和你的自有表数据就在同一个库了。
第二步:配置Membership使用ADO连接字符串
在配置文件的<system.web>节点下,配置MembershipProvider,指定它用刚才的MembershipConn连接字符串:
<system.web> <membership defaultProvider="SqlMembershipProvider"> <providers> <clear /> <!-- 先清空默认的provider,避免冲突 --> <add name="SqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider" connectionStringName="MembershipConn" <!-- 这里指定用MembershipConn --> enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="true" applicationName="/" requiresUniqueEmail="false" passwordFormat="Hashed" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" passwordStrengthRegularExpression="" /> </providers> </membership> </system.web>
这样你调用Membership.CreateUser(...)的时候,Membership就会用这个纯ADO连接字符串,不会再碰EF的那个,自然就不会报metadata的错误了。
第三步:EF正常使用自己的实体连接字符串
你的EF上下文直接用YourEFContext这个连接字符串就行,比如:
public class YourEFContext : DbContext { public YourEFContext() : base("name=YourEFContext") { // 可以加一些EF的配置,比如禁用延迟加载之类的 } // 你的自有表对应的DbSet public DbSet<Product> Products { get; set; } public DbSet<Order> Orders { get; set; } }
这样EF就能正常访问你的自有表,而Membership也能正常操作它的SqlProvider表(比如aspnet_Users、aspnet_Membership这些),两者互不干扰。
要是之后你想用EF来查询或者修改Membership的用户数据(比如查aspnet_Users表),也很简单:
- 打开你的EF模型设计器,右键选择「从数据库更新模型」
- 在弹出的窗口里,选中所有
aspnet_开头的表,点击完成 - 之后你的EF上下文里就会自动生成这些表对应的DbSet,直接用EF操作就行,不用改连接字符串,因为已经是同一个数据库了。
内容的提问来源于stack exchange,提问作者Sead Ordagić

