如何在EF 1/.NET 3.5中创建导航属性实现左连接?
解决EF1数据库优先模式下非主键字段创建导航属性实现左连接的问题
我太懂你在老技术栈里摸爬的痛苦了——EF1确实不支持DefaultIfEmpty(),而且可视化设计器完全不给非主键关联留活路,只能手动改EDMX的XML来搞定。下面是一步步的实操方案:
步骤1:先在设计器里建立临时主键关联(铺垫操作)
先别管非主键的事,按设计器的要求来:
- 右键模型图,添加关联,设置
OnlineClients(0..1)到WAWI_Quittungen(*)的关联,用两个实体的主键来建立关联。 - 这样设计器会自动生成对应的导航属性(比如
WAWI_Quittungen里的OnlineClients属性,OnlineClients里的WAWI_Quittungen集合),先让模型能正常生成代码,避免一开始就报一堆错。
步骤2:手动修改EDMX的XML内容(核心操作)
EF1的EDMX分三个核心部分:CSDL(概念模型)、SSDL(存储模型)、MSL(映射层),我们需要逐个修改:
2.1 修改CSDL(概念模型)
用文本编辑器打开你的EDMX文件,找到<edmx:ConceptualModels>节点下的关联定义(名字应该是你刚才创建的,比如WAWI_Quittungen_OnlineClients),把关联的约束字段从主键改成你要的Client和ClientNr:
<Association Name="WAWI_Quittungen_OnlineClients"> <End Role="OnlineClients" Type="YourModelNamespace.OnlineClients" Multiplicity="0..1" /> <End Role="WAWI_Quittungen" Type="YourModelNamespace.WAWI_Quittungen" Multiplicity="*" /> <ReferentialConstraint> <Principal Role="OnlineClients"> <PropertyRef Name="Client" /> <!-- 替换成OnlineClients的非主键字段 --> </Principal> <Dependent Role="WAWI_Quittungen"> <PropertyRef Name="ClientNr" /> <!-- 替换成WAWI_Quittungen的对应关联字段 --> </Dependent> </ReferentialConstraint> </Association>
2.2 修改SSDL(存储模型)
找到<edmx:StorageModels>节点下的关联映射,把存储层的列映射也改成数据库里对应的Client和ClientNr列:
<AssociationSetMapping Name="WAWI_Quittungen_OnlineClients" TypeName="YourModelNamespace.WAWI_Quittungen_OnlineClients" StoreEntitySet="WAWI_Quittungen"> <EndProperty Name="OnlineClients"> <ScalarProperty Name="Client" ColumnName="Client" /> <!-- 数据库里的列名 --> </EndProperty> <EndProperty Name="WAWI_Quittungen"> <ScalarProperty Name="ClientNr" ColumnName="ClientNr" /> <!-- 数据库里的列名 --> </EndProperty> </AssociationSetMapping>
2.3 验证实体属性存在
确保两个实体的Client和ClientNr属性已经在CSDL里存在(数据库优先模式下,只要你从数据库导入了这些字段,就应该已经生成了)。
步骤3:保存并重新生成模型代码
- 保存EDMX文件,回到Visual Studio,右键模型选择“运行自定义工具”重新生成实体代码。
- 这时候导航属性就会基于你设置的非主键字段关联了。
用导航属性实现左连接
现在你可以直接通过导航属性来实现左连接的效果,比如:
var result = from quittung in context.WAWI_Quittungen select new { QuittungId = quittung.Id, ClientNr = quittung.ClientNr, ClientName = quittung.OnlineClients != null ? quittung.OnlineClients.ClientName : "无关联客户端" };
因为你的关联是0..1到*,EF1会自动生成左连接的SQL语句,完美替代DefaultIfEmpty()的效果。
关键注意事项
- 确保Principal端字段唯一:
OnlineClients的Client字段必须有唯一约束,EF1要求关联的Principal端字段是唯一的,否则会报映射错误。 - 别用“从数据库更新模型”:一旦手动改了EDMX,再用设计器的更新功能会覆盖你的修改,之后得重新改XML。
- 检查名称匹配:XML里的实体名、属性名、数据库列名必须完全匹配,EF1对大小写敏感,别写错字。
内容的提问来源于stack exchange,提问作者Christian Gollhardt
相关产品推荐
相关产品推荐

