【问题标题】:How can I dynamically select my Table at runtime with Dynamic LINQ如何在运行时使用动态 LINQ 动态选择我的表
【发布时间】:2011-06-29 06:26:11
【问题描述】:

我正在开发一个应用程序,允许工程师通过选择数据库、表、字段来对我们的数据库执行简单的单表/视图查询。

我知道如何使用动态 LINQ 库示例在运行时动态选择 Select、Where 和 Order by Clauses,但我在如何分配表选择方面陷入僵局。

有没有办法在运行时动态选择“来自”表,如果你能提供一些具体的例子或指出我的方向吗?

非常感谢你。


编辑


所以两个答案似乎都在说同一个一般的想法。我将尝试将 C# 转换为 VB 并让它工作。

第一个答案转换为

NotInheritable Class DataContextExtensions
    Private Sub New()
    End Sub
    <System.Runtime.CompilerServices.Extension> _
    Public Shared Function GetTableByName(context As DataContext, tableName As String) As ITable
        If context Is Nothing Then
            Throw New ArgumentNullException("context")
        End If
        If tableName Is Nothing Then
            Throw New ArgumentNullException("tableName")
        End If
        Return DirectCast(context.[GetType]().GetProperty(tableName).GetValue(context, Nothing), ITable)
    End Function
End Class

但它向我抛出了一个错误,指出扩展方法只能在模块中定义。 但是当我将它包装在模块标签中时,它仍然会给出同样的错误。

所以我通过将它包装在模块标签中并剥离类标签来编译它。我也可以从中拉出最后一行并将其直接推入我的基本方法中,这样我就可以执行它,但是它似乎又是空的。当我尝试枚举结果时,没有任何结果。不知道这是我的代码问题还是新代码问题,我会测试更多。


这是我对第二个示例的转换,现在我要尝试看看是否可以让它们工作。经过一些测试后,我会带着问题或结果回来。

'get the table from a type (which corresponds to a table in your context)
Dim dataContextNamespace = "My.DataContext.Namespace"
Dim type = Type.[GetType](dataContextNamespace + tableName)
Dim table = dc.GetTable(type

'add where clauses from a list of them
For Each whereClause As String In whereClauses
    table = table.Where(whereClause)
Next

'generate the select clause from a list of columns
Dim query = table.[Select]([String].Format("new({0})"), [String].Join(",", selectColumns))

感谢您的帮助。 BBL

【问题讨论】:

    标签: vb.net linq linq-to-sql dynamic-linq


    【解决方案1】:

    Get table-data from table-name in LINQ DataContext

    使用直接 SQL 语句实际上可能会更好。 LINQ 只会妨碍您。

    VB转换:

    NotInheritable Class DataContextExtensions
        Private Sub New()
        End Sub
        <System.Runtime.CompilerServices.Extension> _
        Public Shared Function GetTableByName(context As DataContext, tableName As String) As ITable
            If context Is Nothing Then
                Throw New ArgumentNullException("context")
            End If
                If tableName Is Nothing Then
                    Throw New ArgumentNullException("tableName")
                End If
            Return DirectCast(context.[GetType]().GetProperty(tableName).GetValue(context, Nothing), ITable)
        End Function
    End Class
    

    用法:

    Dim myDataContext as New MyCustomDataContext
    myDataContext.GetTableByName("ORDERS").Where("...")
    

    【讨论】:

    • 我正在尝试实现这一点,但如何调用扩展方法?重要的是要注意,为了让代码在 VB 中工作,我必须把它放在一个模块中并去掉类标签。
    • 见上面的变化。不确定扩展方法在 VB.Net 中的工作方式是否与在 C# 中相同。
    【解决方案2】:

    您可以使用GetTable()获取您的数据对应的ITable。然后再加上使用DLINQ,就比较容易了。

    此示例使用AdventureWorks 数据库。我的项目在DatabaseTest.AdventureWorks 命名空间的DatabaseTest 程序集中定义了上下文。

    '' need my database and DLINQ extensions up top
    Imports DatabaseTest.AdventureWorks
    Imports System.Linq.Dynamic
    
    '' sample inputs
    Dim dc = New AdventureWorksDataContext()
    Dim tableName = "Contact"
    Dim whereClauses() = {"FirstName = ""John"" OR LastName = ""Smith"""}
    Dim selectColumns() = {"FirstName", "LastName"}
    
    '' get the table from a type (which corresponds to a table in your database)
    Dim typeName = "DatabaseTest.AdventureWorks." & tableName & ", DatabaseTest"
    Dim entityType = Type.GetType(typeName)
    Dim table = dc.GetTable(entityType)
    Dim query As IQueryable = table
    
    '' add where clauses from a list of them
    For Each whereClause As String In whereClauses
        query = query.Where(whereClause)
    Next
    
    '' generate the select clause from a list of columns
    query = query.Select(String.Format("new({0})", String.Join(",", selectColumns)))
    

    回想起来,使用反射可能是获取表的更简单方法,因为您已经有了名称。但是,这些名称可能没有一对一的对应关系,因此您必须对其进行补偿。

    Dim table As ITable = dc.GetType().GetProperty(tableName & "s").GetValue(dc, Nothing)
    

    【讨论】:

    • 试图通过你的@Jess M 工作,但我在使用 var dataContextNamespace = "My.DataContext.Namespace" 时遇到了问题,我应该替换为我的命名空间,所以让它保持原样吗?例如,我的测试表的数据上下文名为 FerrotecLINQ_SQLDataContext 我应该放什么?
    • @Neberu:关键是要获取 LINQ to SQL 类之一的完全限定名称,以便获取与所需表对应的 Type 对象。您需要拥有数据上下文的命名空间(如果有的话),如果适用,还需要程序集。
    猜你喜欢
    • 1970-01-01
    • 2019-06-19
    • 1970-01-01
    • 2013-05-07
    • 1970-01-01
    • 1970-01-01
    • 2010-09-11
    • 1970-01-01
    相关资源
    最近更新 更多