1

私はVB Framework 4.0とLinq to sqlを使用しています。

テーブルの名前を動的に選択したい。table.dllという名前のライブラリを使用し、データベースのすべてのテーブルをマップしましたが、問題ありません。

私の問題は、executequery を実行しようとするときです。ここに私のコード。

Imports Microsoft.VisualBasic
Imports System.Data.Linq
Imports Prototype.NamedTable.Data
Imports Prototype.NamedTable.Utility

    Public Class tipos

        Private _conexion As String = "conexion"

        Public Sub New()

        End Sub

        ...........

        Public Function getConsulta(byval tableName as String) As IList(Of TIPOS)

            Dim context As New DataContext(_conexion)

            sql = " select COD, NAME from " & tableName

            Dim a = context.ExecuteQuery(Of TIPOS)(sql)

            Return sql.ToList

        End Function
    End Class

しかし、エラーがあります。それは英語で次のとおりです。

「タイプ 'Type TIPOS' は、マッピング中に構築されるために、デフォルト (パラメーターなし) コンストラクターを宣言する必要があります」

他のファイルで「TIPOS」を定義しました:

Public Interface TIPOS
    <Column(CanBeNull:=False)> Property COD Integer
    <Column(CanBeNull:=False)> Property NAME As String
End Interface

Public Class ITIPO : Implements TIPO
    Private _cod As Integer
    Private _name As String


    Public Property COD As Integer Implements TIPO.COD
        Get
            Return _cod
        End Get
        Set(ByVal value As Integer)
            _cod = value
        End Set
    End Property

    Public Property NAME As String Implements TIPO.NAME
        Get
            Return _name
        End Get
        Set(ByVal value As String)
            _name = value
        End Set
    End Property

End Class

私は助けが必要です!

私の英語でごめんなさい。

4

2 に答える 2

1

このソリューションは、codeproject.com の記事「LINQ-to-SQL の動的テーブル マッピング」で見つけることができます。以下は、使用できる静的クラスです。4 つの異なる一般的な方法を使用するために必要な手順については、記事を参照してください。呼び出しの例を次に示します。

public interface IResult
{
    [Column(IsPrimaryKey = true)]
    int Id { get; set; }

    [Column]
    string Name { get; set; }

    [Column]
    double Value { get; set; }
}

public void TestThis()
{
    var connectionString = "Data Source=.\SQLEXPRESS;Initial Catalog=YourDatabaseName;Integrated Security=True;Pooling=False";
    var context = new DataContext(connectionString);
    var table = context.GetTable<IResult>("YourTableName");
    var query = from r in table where r.Id == 108 select r;
    var list = query.ToList();
}

クラスコード:

namespace Prototype.NamedTable
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.Linq;
using System.Data.Linq.Mapping;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;

/// <summary>
/// The utility.
/// </summary>
public static class Utility
{
    #region Constants and Fields

    /// <summary>
    /// The named types.
    /// </summary>
    private static readonly Dictionary<string, Type> NamedTypes = new Dictionary<string, Type>();

    /// <summary>
    /// The _assembly builder.
    /// </summary>
    private static AssemblyBuilder _assemblyBuilder;

    /// <summary>
    /// The _module builder.
    /// </summary>
    private static ModuleBuilder _moduleBuilder;

    #endregion

    #region Properties

    /// <summary>
    /// Gets or sets a value indicating whether Verbose.
    /// </summary>
    public static bool Verbose { get; set; }

    #endregion

    #region Public Methods

    /// <summary>
    /// The clear.
    /// </summary>
    public static void Clear()
    {
        _assemblyBuilder = null;
        NamedTypes.Clear();
    }

    /// <summary>
    /// Retrieve a table from the data context which implements ITable&lt;TEntity&gt; by T and use ITable&lt;TBack&gt;
    /// </summary>
    /// <typeparam name="TEntity">
    /// Entity Type
    /// </typeparam>
    /// <typeparam name="TBack">
    /// Backing Type
    /// </typeparam>
    /// <param name="context">
    /// Data Context
    /// </param>
    /// <returns>
    /// </returns>
    public static ATable<TEntity> GetTable<TEntity, TBack>(this DataContext context) where TEntity : class
        where TBack : class
    {
        // Create the backup table
        Table<TBack> refer = context.GetTable<TBack>();

        // Prepare the cloning method
        Delegate cloneFrom = CompileCloning(typeof(TEntity), typeof(TBack));

        // Construct the table wrapper
        return new ATable<TEntity>(refer, cloneFrom);
    }

    /// <summary>
    /// Retrieve a table from the data context which implements ITable&lt;TEntity&gt; uses specific backing table
    /// </summary>
    /// <typeparam name="TEntity">
    /// Entity Type
    /// </typeparam>
    /// <param name="context">
    /// Data context
    /// </param>
    /// <param name="name">
    /// Table name
    /// </param>
    /// <returns>
    /// </returns>
    public static ATable<TEntity> GetTable<TEntity>(this DataContext context, string name) where TEntity : class
    {
        // Create/Retrieve a type definition for the table using the TEntity type
        Type type = DefineEntityType(typeof(TEntity), name);

        // Create the backup table using the new type
        ITable refer = context.GetTable(type);

        // Prepare the cloning method
        Delegate cloneFrom = CompileCloning(typeof(TEntity), type);

        // Construct the table wrapper
        return new ATable<TEntity>(refer, cloneFrom);
    }

    /*
    /// <summary>
    /// The log.
    /// </summary>
    /// <param name="format">
    /// The format.
    /// </param>
    /// <param name="args">
    /// The args.
    /// </param>
    public static void Log(string format, params object[] args)
    {
        if (!Verbose)
        {
            return;
        }

        Console.Write("*** ");

        if ((args == null) || (args.Length == 0))
        {
            Console.WriteLine(format);
        }
        else
        {
            Console.WriteLine(format, args);
        }
    }*/

    #endregion

    #region Methods

    /// <summary>
    /// Clone an attribute
    /// </summary>
    /// <param name="attr">
    /// </param>
    /// <returns>
    /// </returns>
    private static CustomAttributeBuilder CloneColumn(object attr)
    {
        Type source = attr.GetType();
        Type target = typeof(ColumnAttribute);

        var props = new List<PropertyInfo>();
        var values = new List<object>();

        // Extract properties and their values
        foreach (PropertyInfo prop in source.GetProperties())
        {
            if (!prop.CanRead || !prop.CanWrite)
            {
                continue;
            }

            props.Add(target.GetProperty(prop.Name));
            values.Add(prop.GetValue(attr, null));
        }

        // Create a new attribute using the properties and values
        return new CustomAttributeBuilder(
            target.GetConstructor(Type.EmptyTypes), new object[0], props.ToArray(), values.ToArray());
    }

    /// <summary>
    /// Make a delegate that copy content from "source" to "dest"
    /// </summary>
    /// <param name="source">
    /// Source Type
    /// </param>
    /// <param name="dest">
    /// Destination Type
    /// </param>
    /// <returns>
    /// Executable delegate
    /// </returns>
    private static Delegate CompileCloning(Type source, Type dest)
    {
        // Input parameter
        ParameterExpression input = Expression.Parameter(source);

        // For every property, create a member binding
        List<MemberBinding> binds =
            source.GetProperties().Select(
                prop =>
                Expression.Bind(
                    dest.GetProperty(
                        prop.Name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly), 
                    Expression.MakeMemberAccess(input, prop))).Cast<MemberBinding>().ToList();

        // Expression of creating the new object
        MemberInitExpression body = Expression.MemberInit(
            Expression.New(dest.GetConstructor(Type.EmptyTypes)), binds);

        // The final lambda
        LambdaExpression lambda = Expression.Lambda(body, input);

        // MJE
        //Log("{0}", lambda.ToString());

        // Return the executable delegate
        return lambda.Compile();
    }

    /// <summary>
    /// Create a class based on the template interface
    /// </summary>
    /// <param name="template">
    /// </param>
    /// <param name="name">
    /// </param>
    /// <returns>
    /// </returns>
    private static Type DefineEntityType(Type template, string name)
    {
        // Prepare the builders if not done
        if (_assemblyBuilder == null)
        {
            _assemblyBuilder =
                AppDomain.CurrentDomain.DefineDynamicAssembly(
                    new AssemblyName(Guid.NewGuid().ToString()), AssemblyBuilderAccess.Run);

            _moduleBuilder = _assemblyBuilder.DefineDynamicModule("Types");
        }

        // Check if there is already a type created for that table
        if (NamedTypes.ContainsKey(name))
        {
            return NamedTypes[name];
        }

        // Create the new type
        TypeBuilder tbuilder = null;
        if (template.IsInterface)
        {
            tbuilder = DefineInterfaceChild(name, template);
        }
        else
        {
            tbuilder = DefineOverriddenChild(name, template);
        }

        Type final = tbuilder.CreateType();

        NamedTypes[name] = final;

        return final;
    }

    /// <summary>
    /// The define interface child.
    /// </summary>
    /// <param name="name">
    /// The name.
    /// </param>
    /// <param name="template">
    /// The template.
    /// </param>
    /// <returns>
    /// </returns>
    private static TypeBuilder DefineInterfaceChild(string name, Type template)
    {
        TypeBuilder tbuilder = _moduleBuilder.DefineType(
            name, TypeAttributes.Public, typeof(Object), new[] { template });

        // Default constructor
        tbuilder.DefineDefaultConstructor(MethodAttributes.Public);

        // Attach Table attribute
        var abuilder = new CustomAttributeBuilder(
            typeof(TableAttribute).GetConstructor(Type.EmptyTypes), 
            new object[0], 
            new[] { typeof(TableAttribute).GetProperty("Name") }, 
            new object[] { name });
        tbuilder.SetCustomAttribute(abuilder);

        List<PropertyInfo> properties = template.GetProperties().ToList(); // May require sorting

        // Implement all properties));
        foreach (PropertyInfo prop in properties)
        {
            // Define backing field
            FieldBuilder fbuilder = tbuilder.DefineField(
                "_" + prop.Name, prop.PropertyType, FieldAttributes.Private);

            // Define get method
            MethodBuilder pgbuilder = tbuilder.DefineMethod(
                "get_" + prop.Name, 
                MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig
                | MethodAttributes.Virtual | MethodAttributes.Final, 
                prop.PropertyType, 
                Type.EmptyTypes);

            // Define get method body { return _field; }
            ILGenerator ilg = pgbuilder.GetILGenerator();
            ilg.Emit(OpCodes.Ldarg_0);
            ilg.Emit(OpCodes.Ldfld, fbuilder);
            ilg.Emit(OpCodes.Ret);

            // Define set method
            MethodBuilder psbuilder = tbuilder.DefineMethod(
                "set_" + prop.Name, 
                MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig
                | MethodAttributes.Virtual | MethodAttributes.Final, 
                null, 
                new[] { prop.PropertyType });

            // Define set method body { _field = value; }
            ILGenerator ils = psbuilder.GetILGenerator();
            ils.Emit(OpCodes.Ldarg_0);
            ils.Emit(OpCodes.Ldarg_1);
            ils.Emit(OpCodes.Stfld, fbuilder);
            ils.Emit(OpCodes.Ret);

            // Define the property
            PropertyBuilder pbuilder = tbuilder.DefineProperty(
                prop.Name, PropertyAttributes.None, CallingConventions.Standard, prop.PropertyType, null);

            // Set get/set method
            pbuilder.SetGetMethod(pgbuilder);
            pbuilder.SetSetMethod(psbuilder);

            // Attach Column attribute
            foreach (object attr in prop.GetCustomAttributes(false))
            {
                if (attr is ColumnAttribute || attr is AlterColumnAttribute)
                {
                    // MJE
                    //Log("Create column attribute for {0}", prop.Name);
                    pbuilder.SetCustomAttribute(CloneColumn(attr));
                    break;
                }
            }
        }

        return tbuilder;
    }

    /// <summary>
    /// The define overridden child.
    /// </summary>
    /// <param name="name">
    /// The name.
    /// </param>
    /// <param name="template">
    /// The template.
    /// </param>
    /// <returns>
    /// </returns>
    private static TypeBuilder DefineOverriddenChild(string name, Type template)
    {
        TypeBuilder tbuilder = _moduleBuilder.DefineType(name, TypeAttributes.Public, template);

        // Default constructor
        tbuilder.DefineDefaultConstructor(MethodAttributes.Public);

        // Attach Table attribute
        var abuilder = new CustomAttributeBuilder(
            typeof(TableAttribute).GetConstructor(Type.EmptyTypes), 
            new object[0], 
            new[] { typeof(TableAttribute).GetProperty("Name") }, 
            new object[] { name });
        tbuilder.SetCustomAttribute(abuilder);

        List<PropertyInfo> properties = template.GetProperties().ToList(); // May require sorting

        // Implement all properties));
        foreach (PropertyInfo prop in properties)
        {
            // Define get method
            MethodBuilder pgbuilder = tbuilder.DefineMethod(
                "get_" + prop.Name, 
                MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig
                | MethodAttributes.Virtual | MethodAttributes.Final, 
                prop.PropertyType, 
                Type.EmptyTypes);

            // Define get method body { return _field; }
            ILGenerator ilg = pgbuilder.GetILGenerator();
            ilg.Emit(OpCodes.Ldarg_0);
            ilg.Emit(OpCodes.Call, template.GetMethod("get_" + prop.Name));
            ilg.Emit(OpCodes.Ret);

            // Define set method
            MethodBuilder psbuilder = tbuilder.DefineMethod(
                "set_" + prop.Name, 
                MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig
                | MethodAttributes.Virtual | MethodAttributes.Final, 
                null, 
                new[] { prop.PropertyType });

            // Define set method body { _field = value; }
            ILGenerator ils = psbuilder.GetILGenerator();
            ils.Emit(OpCodes.Ldarg_0);
            ils.Emit(OpCodes.Ldarg_1);
            ils.Emit(OpCodes.Call, template.GetMethod("set_" + prop.Name));
            ils.Emit(OpCodes.Ret);

            // Define the property
            PropertyBuilder pbuilder = tbuilder.DefineProperty(
                prop.Name, PropertyAttributes.None, CallingConventions.Standard, prop.PropertyType, null);

            // Set get/set method
            pbuilder.SetGetMethod(pgbuilder);
            pbuilder.SetSetMethod(psbuilder);

            // Attach Column attribute
            foreach (object attr in prop.GetCustomAttributes(false))
            {
                if (attr is ColumnAttribute || attr is AlterColumnAttribute)
                {
                    // MJE
                    //Log("Create column attribute for {0}", prop.Name);
                    pbuilder.SetCustomAttribute(CloneColumn(attr));
                    break;
                }
            }
        }

        return tbuilder;
    }

    #endregion

    /// <summary>
    /// A table wrapper implements ITable&lt;TEntity&gt; backed by other ITable object
    /// </summary>
    /// <typeparam name="TEntity">
    /// </typeparam>
    public class ATable<TEntity> : ITable<TEntity>
        where TEntity : class
    {
        #region Constants and Fields

        /// <summary>
        /// Cloning method
        /// </summary>
        private readonly Delegate _clone;

        /// <summary>
        /// Backing table
        /// </summary>
        private readonly ITable _internal;

        #endregion

        #region Constructors and Destructors

        /// <summary>
        /// Initializes a new instance of the <see cref="ATable{TEntity}"/> class. 
        /// Construct from backing table
        /// </summary>
        /// <param name="inter">
        /// </param>
        /// <param name="from">
        /// </param>
        public ATable(ITable inter, Delegate from)
        {
            this._internal = inter;
            this._clone = from;
        }

        #endregion

        #region Properties

        /// <summary>
        /// Gets ElementType.
        /// </summary>
        public Type ElementType
        {
            get
            {
                // Use the backing table element
                return this._internal.ElementType;
            }
        }

        /// <summary>
        /// Gets Expression.
        /// </summary>
        public Expression Expression
        {
            get
            {
                // Use the backing table expression
                return this._internal.Expression;
            }
        }

        /// <summary>
        /// Gets Provider.
        /// </summary>
        public IQueryProvider Provider
        {
            get
            {
                // Use the backing table provider
                return this._internal.Provider;
            }
        }

        #endregion

        #region Implemented Interfaces

        #region IEnumerable

        /// <summary>
        /// The get enumerator.
        /// </summary>
        /// <returns>
        /// </returns>
        /// <exception cref="NotImplementedException">
        /// </exception>
        IEnumerator IEnumerable.GetEnumerator()
        {
            throw new NotImplementedException();
        }

        #endregion

        #region IEnumerable<TEntity>

        /// <summary>
        /// The get enumerator.
        /// </summary>
        /// <returns>
        /// </returns>
        /// <exception cref="NotImplementedException">
        /// </exception>
        public IEnumerator<TEntity> GetEnumerator()
        {
            throw new NotImplementedException();
        }

        #endregion

        #region ITable<TEntity>

        /// <summary>
        /// The attach.
        /// </summary>
        /// <param name="entity">
        /// The entity.
        /// </param>
        /// <exception cref="NotImplementedException">
        /// </exception>
        public void Attach(TEntity entity)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// The delete on submit.
        /// </summary>
        /// <param name="entity">
        /// The entity.
        /// </param>
        public void DeleteOnSubmit(TEntity entity)
        {
            // Directly invoke the backing table
            this._internal.DeleteOnSubmit(entity);
        }

        /// <summary>
        /// The insert on submit.
        /// </summary>
        /// <param name="entity">
        /// The entity.
        /// </param>
        public void InsertOnSubmit(TEntity entity)
        {
            // Input entity must be changed to backing type
            object v = this._clone.DynamicInvoke(entity);

            // Invoke the backing table
            this._internal.InsertOnSubmit(v);
        }

        #endregion

        #endregion
    }

    /// <summary>
    /// The alter column attribute.
    /// </summary>
    public class AlterColumnAttribute : Attribute
    {
        #region Constants and Fields

        /// <summary>
        /// The _can be null.
        /// </summary>
        private bool _canBeNull = true;

        /// <summary>
        /// The _update check.
        /// </summary>
        private UpdateCheck _updateCheck = UpdateCheck.Always;

        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets AutoSync.
        /// </summary>
        public AutoSync AutoSync { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether CanBeNull.
        /// </summary>
        public bool CanBeNull
        {
            get
            {
                return this._canBeNull;
            }

            set
            {
                this._canBeNull = value;
            }
        }

        /// <summary>
        /// Gets or sets DbType.
        /// </summary>
        public string DbType { get; set; }

        /// <summary>
        /// Gets or sets Expression.
        /// </summary>
        public string Expression { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether IsDbGenerated.
        /// </summary>
        public bool IsDbGenerated { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether IsDiscriminator.
        /// </summary>
        public bool IsDiscriminator { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether IsPrimaryKey.
        /// </summary>
        public bool IsPrimaryKey { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether IsVersion.
        /// </summary>
        public bool IsVersion { get; set; }

        /// <summary>
        /// Gets or sets UpdateCheck.
        /// </summary>
        public UpdateCheck UpdateCheck
        {
            get
            {
                return this._updateCheck;
            }

            set
            {
                this._updateCheck = value;
            }
        }

        #endregion
    }
}
}
于 2013-08-02T04:07:29.697 に答える
0

Linq-to-Sql はインターフェイスを具体化できません。クエリからどのインスタンスを作成する必要があるかを知るには、クラス仕様が必要です。控えめに言っても、例外メッセージはとらえどころのないものです。なぜそれがもっと要点に合わないのかわかりません。

マテリアライズするクラスはマップされている必要があることに注意してください。または、dbml にある必要があります。私がこれを言うのは、あなたのITIPOクラスが部分的ではないためです。そのため、インターフェイスを実装するにはどうすればよいのか疑問に思います (まあ、コードをスリム化しただけかもしれません)。

補足: クラス名にすべて大文字を使用しないでください。また、クラスではなく "I" をインターフェイス仕様の前に付けてください。

于 2012-12-17T12:45:57.263 に答える