EF dbcontext 在 dynamo 自定义节点中返回一个空的 dbset

Posted

技术标签:

【中文标题】EF dbcontext 在 dynamo 自定义节点中返回一个空的 dbset【英文标题】:EF dbcontext return an empty dbset in dynamo custom node 【发布时间】:2021-06-19 05:11:39 【问题描述】:

我想在 Dynamo 节点中创建一个下拉列表来选择一个项目并返回属性。

我有一个解决方案,其中有 3 个项目。一个项目是数据库的连接器,由其他两个项目中的任何一个使用。

另外两个项目本质上是 UI,用于显示从数据库中获取的项目。一个是 WPF 应用程序,另一个是 Dynamo 节点。

当我使用 WPF 应用程序时,连接器 dbcontext 中的数据返回带有值的 dbset。但是当我将连接器与 Dynamo 节点一起使用时,连接器返回一个空的数据库集。因此节点中的组合框为空。

连接器 dbcontext

using Autodesk.DesignScript.Runtime;
using System.Data.Entity;

namespace ConnectToDB

    [IsVisibleInDynamoLibrary(false)]
    public partial class ShapesModelContext : DbContext
    
        [IsVisibleInDynamoLibrary(false)]
        public ShapesModelContext()
            : base("ShapesModelContext")
        
        

        public DbSet<C> C  get; set; 
        public DbSet<C_m> C_m  get; set; 
        public DbSet<HP> HPs  get; set; 
        public DbSet<HP_m> HP_m  get; set; 
        public DbSet<HSS> HSSes  get; set; 
        public DbSet<HSS_m> HSS_m  get; set; 
        public DbSet<L> L  get; set; 
        public DbSet<L_m> L_m  get; set; 
        public DbSet<M> M  get; set; 
        public DbSet<M_m> M_m  get; set; 
        public DbSet<MC> MCs  get; set; 
        public DbSet<MC_m> MC_m  get; set; 
        public DbSet<MT> MTs  get; set; 
        public DbSet<MT_m> MT_m  get; set; 
        public DbSet<PIPE> PIPEs  get; set; 
        public DbSet<PIPE_m> PIPE_m  get; set; 
        public DbSet<S> S  get; set; 
        public DbSet<S_m> S_m  get; set; 
        public DbSet<ShapesID> ShapesIDs  get; set; 
        public DbSet<ST> STs  get; set; 
        public DbSet<ST_m> ST_m  get; set; 
        public DbSet<sysdiagram> sysdiagrams  get; set; 
        public DbSet<TwoL> TwoLs  get; set; 
        public DbSet<TwoL_m> TwoL_m  get; set; 
        public DbSet<W> W  get; set; 
        public DbSet<W_m> W_m  get; set; 
        public DbSet<WT> WTs  get; set; 
        public DbSet<WT_m> WT_m  get; set; 

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        
            modelBuilder.Entity<ShapesID>()
                .HasOptional(e => e.C)
                .WithRequired(e => e.ShapesID);

            modelBuilder.Entity<ShapesID>()
                .HasOptional(e => e.HP)
                .WithRequired(e => e.ShapesID);

            modelBuilder.Entity<ShapesID>()
                .HasOptional(e => e.HSS)
                .WithRequired(e => e.ShapesID);

            modelBuilder.Entity<ShapesID>()
                .HasOptional(e => e.L)
                .WithRequired(e => e.ShapesID);

            modelBuilder.Entity<ShapesID>()
                .HasOptional(e => e.M)
                .WithRequired(e => e.ShapesID);

            modelBuilder.Entity<ShapesID>()
                .HasOptional(e => e.MC)
                .WithRequired(e => e.ShapesID);

            modelBuilder.Entity<ShapesID>()
                .HasOptional(e => e.MT)
                .WithRequired(e => e.ShapesID);

            modelBuilder.Entity<ShapesID>()
                .HasOptional(e => e.PIPE)
                .WithRequired(e => e.ShapesID);

            modelBuilder.Entity<ShapesID>()
                .HasOptional(e => e.S)
                .WithRequired(e => e.ShapesID);

            modelBuilder.Entity<ShapesID>()
                .HasOptional(e => e.ST)
                .WithRequired(e => e.ShapesID);

            modelBuilder.Entity<ShapesID>()
                .HasOptional(e => e.TwoL)
                .WithRequired(e => e.ShapesID);

            modelBuilder.Entity<ShapesID>()
                .HasOptional(e => e.W)
                .WithRequired(e => e.ShapesID);

            modelBuilder.Entity<ShapesID>()
                .HasOptional(e => e.WT)
                .WithRequired(e => e.ShapesID);
        
    

视图模型和获取数据的方法。

using System.Collections.Generic;
using Newtonsoft.Json;


namespace ConnectToDB

    public class AISC_ShapesViewModel
    

        private List<string> _Shapes;

        public List<string> Shapes
        
            get
            
                return _Shapes;
                
               
            set
            
                _Shapes = value;
            
        

        public List<string> LoadSections()
        
            List<string> thaColl = new List<string>();

            using (var context = new ShapesModelContext())
            
                var sections = context.ShapesIDs;
                foreach (var section in context.ShapesIDs)
                
                    thaColl.Add(section.EDI_Std_Nomenclature);
                

            

            return Shapes = thaColl;
        
    

在组合框中正确显示数据的 WPF 应用程序。

<Window x:Class="WPFUI.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WPFUI"
        xmlns:vm="clr-namespace:ConnectToDB;assembly=ConnectToDB"
        Loaded="Main_Loaded"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <vm:AISC_ShapesViewModel x:Key="thaMidClass"/>
    </Window.Resources>
    <Grid DataContext="Binding Mode=OneWay, Source=StaticResource thaMidClass">
        <ComboBox x:Name="comboBox" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="120" ItemsSource="Binding Shapes"/>
        <Label x:Name="section" Content="Binding SelectedItem, ElementName=comboBox" HorizontalAlignment="Left" Margin="173,10,0,0" VerticalAlignment="Top" Width="291" Height="22" FontSize="10"/>

    </Grid>
</Window>

我的 Dynamo 节点的用户控件不显示数据。

<UserControl x:Class="DynamoUI.Dynamo_UI"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:DynamoUI"
             xmlns:vm="clr-namespace:ConnectToDB;assembly=ConnectToDB"
             Loaded="Comboloaded"
             mc:Ignorable="d" Height="73.5" Width="219.5">
    <UserControl.Resources>
        <vm:AISC_ShapesViewModel x:Key="thaMidClass"/>
    </UserControl.Resources>

    <Grid DataContext="StaticResource thaMidClass">
        <ComboBox x:Name="comboBox" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="193" ItemsSource="Binding Path=Shapes"/>

    </Grid>
</UserControl>

节点模型。

using CoreNodeModels;
using Dynamo.Graph.Nodes;
using Newtonsoft.Json;

namespace DynamoUI

    [NodeName("AISC Shapes")]
    [NodeDescription("Query AISC shapes database")]
    [NodeCategory("AISC.Shapes Node")]
    //[InPortNames("A")]
    //[InPortTypes("List")]
    //[InPortDescriptions("List A")]
    [OutPortNames("Output")]
    [OutPortTypes("Dictionary")]
    [OutPortDescriptions("Shape properties dictionary")]
    [IsDesignScriptCompatible]
    class AISC_Shape_Node_Model: NodeModel
    
        [JsonConstructor]
        public AISC_Shape_Node_Model()
        
            RegisterAllPorts();
        

    


节点视图。

using Dynamo.Controls;
using Dynamo.Wpf;

namespace DynamoUI

    class AISC_Shape_Node_View : INodeViewCustomization<AISC_Shape_Node_Model>
    
        public void CustomizeView(AISC_Shape_Node_Model model, NodeView nodeView)
        
            var ui = new Dynamo_UI();
            nodeView.inputGrid.Children.Add(ui);
            ui.DataContext = model;
        

        public void Dispose()
        
        
    


连接字符串。

  <connectionStrings>
    <add name="ShapesModelContext" connectionString="data source=MyDatabase;initial catalog=AISC_Shapes_V15;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />
  </connectionStrings>

带有 Dynamo 节点。

使用 WPF 应用程序。

每次使用WPF前端时,都会调用这个方法。

        public List<string> LoadSections()
        
            List<string> thaColl = new List<string>();

            using (var context = new ShapesModelContext())
            
                var sections = context.ShapesIDs;
                foreach (var section in context.ShapesIDs)
                
                    thaColl.Add(section.EDI_Std_Nomenclature);
                

            

            return Shapes = thaColl;
        

并且,在调试步骤中,我们可以看到创建了从 EF DbContext 继承的“ShapesModelContext”,并将 ShapesIDs DbSet 分配给了部分。代码进入 for 循环并遍历 DbSet。

但是,当我使用 Dynamo NodeModel 作为前端时,会执行相同的代码,但在 for 循环中,它会检查 DbSet 并立即退出循环,因为 DbSet 为空。

【问题讨论】:

这 3 个项目的连接字符串是什么?通常如果连接字符串不同,结果也会不同。 所有项目的连接字符串都相同。我将一个 ui 项目切换到另一个。当我使用 WPF 应用程序时,它工作正常,但当我使用 Dynamo 节点时,组合框为空。 为什么DataContext不同? 我对 WPF 应用程序和 Dynamo 节点使用相同的 dbcontext。为什么你认为有不同? 1) 【参考方案1】:

问题在于 Dynamo 使用自己的连接字符串。连接字符串指向:

Data Source=(localdb)\mssqllocaldb

初始目录名称由在 DbContext 中找到的连接字符串名称定义。

Initial Catalog=ShapesModelContext

因此我更改了我的 LoadSections() 方法以指定正确的连接字符串。

原来的代码是:

        public List<string> LoadSections()
        
            List<string> thaColl = new List<string>();

            using (var context = new ShapesModelContext())
            
                var sections = context.ShapesIDs;
                foreach (var section in context.ShapesIDs)
                
                    thaColl.Add(section.EDI_Std_Nomenclature);
                

            

            return Shapes = thaColl;
        

现在添加了连接字符串。

            using (var context = new ShapesModelContext())
            
                context.Database.Connection.ConnectionString = "data source=XXXXX;initial catalog=XXXXXXXX;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework";
                var sections = context.ShapesIDs;
                foreach (var section in sections)
                
                    thaColl.Add(section.EDI_Std_Nomenclature);
                
            

            return Shapes = thaColl; 

【讨论】:

以上是关于EF dbcontext 在 dynamo 自定义节点中返回一个空的 dbset的主要内容,如果未能解决你的问题,请参考以下文章

Abp vNext 自定义 Ef Core 仓储引发异常

如何在 EF Core 5 中为自定义 SQL 配置导航属性

如何在 EF Core Code First 中自定义迁移生成?

EF生成 类型“System.Data.Entity.DbContext”在未被引用的程序集中定义

Kotlin Dynamo DB 自定义转换器

自定义ValidateEntity实体验证及DB层面Interception拦截EF中的Execute