CodeSmith操作Access时字段的排序问题

最近在用CodeSmith操作写ACCESS数据库的代码模版,发现CodeSmith默认的字段顺序与ACCESS中表的字段顺序不一致。

首先在ACCESS数据库中建一个测试表Test,并添加ID、Name等几个字段,如下图所示:

然后在CodeSmith中新建一个模版,并循环输出所有字段名

 <%@ CodeTemplate Language="C#" TargetLanguage="C#" ResponseEncoding="UTF-8"%>
<%@ Property Name="SourceTable" Type="SchemaExplorer.TableSchema" Category="Context" Description="数据表" %>
<%@ Assembly Name="SchemaExplorer" %>
<%@ Import Namespace="SchemaExplorer" %>

<%for(int i=0;i<SourceTable.Columns.Count;i++){%>
<%=SourceTable.Columns[i].Name%>
<%}%>

运行后得到

Age
ID
IsOK
Name
Remark
Time

我们可以看到,字段是按照字典顺序排序的,而不是实际数据表中的顺序。虽然这不影响什么,但是一想到自动生成的MODEL层的字段和数据表的不对应,总感觉不太爽。
我甚至将SourceTable.Columns[i].ExtendedProperties这个扩展属性全部输出,也没有得到什么有用的信息。

后来无意中,我在.NET的 OleDbConnection.GetOleDbSchemaTable中得到了字段的顺序,新建一个winform项目,代码如下

1 string accessConnection = "Provider=Microsoft.Jet.OLEDB.4.0;Jet OLEDB:Database Password=123456;Data Source=c:\\db1.mdb;Persist Security Info=True";
2 OleDbConnection connection = new OleDbConnection(accessConnection);
3 connection.Open();
4 DataTable schemaColumns = connection.GetOleDbSchemaTable(OleDbSchemaGuid.Columns, new string[] { null, null, "test", null });
5 dataGridView2.DataSource = schemaColumns;
6 connection.Close();

我将GetOleDbSchemaTable获取到信息都绑定到一个DataGridView控件中,这样对里面的数据可以有一个比较直观的了解

终于看到了字段真正顺序!那么接下来的事情就比较好办了,我们要在CodeSmith中获取这个SchemaTable,然后根据ORDINAL_POSITION的值重新对SourceTable.Columns进行排序,这样后面编写代码模版的时候,字段顺序就是正常的了。CodeSmith代码如下:

复制代码
<%@ CodeTemplate Language="C#" TargetLanguage="C#" ResponseEncoding="UTF-8"%>
<%@ Property Name="SourceTable" Type="SchemaExplorer.TableSchema" Category="Context" Description="数据表" %>
<%@ Assembly Name="SchemaExplorer" %>
<%@ Import Namespace="SchemaExplorer" %>
<%@ Import Namespace="System.Data.OleDb" %>
<%FixColumns();%>

<%for(int i=0;i<SourceTable.Columns.Count;i++){%>
<%=SourceTable.Columns[i].Name%>
<%}%>

<script runat="template">
//由于SourceTable.Columns的顺序默认是按字段名升序排列,因此需要根据"ORDINAL_POSITION"的值来重新排序
public void FixColumns()
{
    OleDbConnection connection = new OleDbConnection(SourceTable.Database.ConnectionString);
    connection.Open();
    DataTable schemaColumns = connection.GetOleDbSchemaTable(OleDbSchemaGuid.Columns, new string[] { null, null, SourceTable.Name, null });
    connection.Close();
    
    for(int i=schemaColumns.Rows.Count;i>0;i--)
    {
        for(int j=0;j<schemaColumns.Rows.Count;j++)
        {
            if(Convert.ToInt32(schemaColumns.Rows[j]["ORDINAL_POSITION"].ToString())==i)
            {
                int m=0;
                for(m=0;m<SourceTable.Columns.Count;m++)
                {
                    if(SourceTable.Columns[m].Name==schemaColumns.Rows[j]["COLUMN_NAME"].ToString())
                    {
                        break;    
                    }
                }
                ColumnSchema col=SourceTable.Columns[m];
                SourceTable.Columns.RemoveAt(m);
                SourceTable.Columns.Insert(0,col);
            }
        }
    }
}
</script>
复制代码

代码不难理解,我用了类似插入排序的思路,从排序最后的字段开始往前查找(即ORDINAL_POSITION值从最大到最小),查找到了后就插入到SourceTable.Columns集合的最前面。这样到最后的结果就是SourceTable.Columns集合按ORDINAL_POSITION值从小到大排序了。

 

posted on   小小娟  阅读(786)  评论(0编辑  收藏  举报

编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· 展开说说关于C#中ORM框架的用法!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示