Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/270.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 有没有更好的方法将对象从数据库查询映射到对象?_C#_Oracle_Database Connection_Extension Methods - Fatal编程技术网

C# 有没有更好的方法将对象从数据库查询映射到对象?

C# 有没有更好的方法将对象从数据库查询映射到对象?,c#,oracle,database-connection,extension-methods,C#,Oracle,Database Connection,Extension Methods,我想知道是否有更好的方法来解决我忽视的这个问题。(我在寻求第二种意见) 我想使用“Oracle.DataAccess.Client”创建一种通用且简单的方法,将对象绑定到数据库读取器查询 为了做到这一点,我最初想创建一个从OracleCommand继承的对象;但是,OracleCommand是一个密封对象 为了解决这个问题,我决定创建一个扩展方法,尝试将对象映射到数据库中每一行的通用列 编辑:在我的场景中,我知道数据库将是什么样子;但是,在运行时之前,我不知道数据库在哪里。i、 e.数据库可能已

我想知道是否有更好的方法来解决我忽视的这个问题。(我在寻求第二种意见)

我想使用“Oracle.DataAccess.Client”创建一种通用且简单的方法,将对象绑定到数据库读取器查询

为了做到这一点,我最初想创建一个从OracleCommand继承的对象;但是,OracleCommand是一个密封对象

为了解决这个问题,我决定创建一个扩展方法,尝试将对象映射到数据库中每一行的通用列

编辑:在我的场景中,我知道数据库将是什么样子;但是,在运行时之前,我不知道数据库在哪里。i、 e.数据库可能已提前传输,最终用户将在运行时指定数据库的凭据

以下是实施方案:

public static T[] Bind<T>(this OracleCommand oe, Binding binding, CommandBehavior Behavior = CommandBehavior.Default)
    {
        List<T> ret = new List<T>();

        using (var reader = oe.ExecuteReader(Behavior))
        {
            while (reader.Read())
            {
                T unknownObj = (T)Activator.CreateInstance(typeof(T));
                for (int i = 0; i < binding.GetBindCount(); i++)
                {
                    var propinfo = unknownObj.GetType().GetProperties().ToList();
                    var prop = propinfo.Find((p) => p.Name == binding.GetBindValue(i, true));
                    prop.SetValue(unknownObj, reader[binding.GetBindValue(i, false)]);
                }
                ret.Add(unknownObj);
            }
        }
        return ret.ToArray();
    }
}

public class Binding
{

    List<BindingMap> _map = new List<BindingMap>();


    public void AddBind(String VariableName, String ColumnName)
    {
        _map.Add(new BindingMap(VariableName, ColumnName));
    }
    public String GetBindValue(int index, bool IsVariable = true)
    {
        var a = _map.ToArray();
        return (IsVariable) ? a[index].Variable : a[index].Column;
    }

    public int GetBindCount()
    {
        return _map.Count;
    }
}

public class BindingMap
{
    public String Column;
    public String Variable;

    public BindingMap(String v, String c)
    {
        Variable = v;
        Column = c;
    }
}
publicstatict[]Bind(此OracleCommand oe,绑定绑定,CommandBehavior=CommandBehavior.Default)
{
List ret=新列表();
使用(变量读取器=oe.ExecuteReader(行为))
{
while(reader.Read())
{
T unknownObj=(T)Activator.CreateInstance(typeof(T));
for(int i=0;ip.Name==binding.GetBindValue(i,true));
prop.SetValue(unknownObj,reader[binding.GetBindValue(i,false)];
}
ret.Add(未知nobj);
}
}
返回返回返回到阵列();
}
}
公共类绑定
{
列表_map=新列表();
public void AddBind(字符串变量名、字符串列名)
{
_Add(新的BindingMap(VariableName,ColumnName));
}
公共字符串GetBindValue(int索引,bool IsVariable=true)
{
var a=_map.ToArray();
返回值(IsVariable)?a[index]。变量:a[index]。列;
}
public int GetBindCount()
{
返回_map.Count;
}
}
公共类绑定映射
{
公共字符串列;
公共字符串变量;
公共绑定映射(字符串v、字符串c)
{
变量=v;
列=c;
}
}
有没有更好的方法来做到这一点,我忽略了,或者这是一个声音

在实际代码中使用它的方式如下:

 static void Main()
    {           
        Binding b = new Binding();
        b.AddBind("CreatedBy", "Create_by");


        using (var Conn = new OracleConnection())
        {
            Conn.ConnectionString = od.Options.GetConnectionString();
            using (var Command = new OracleCommand())
            {
                Command.Connection = Conn;
                Command.CommandText = "Select * From Accounts";

                Conn.Open();

                var a = Command.Bind<Account>(b);
                foreach (Account e in a)
                {
                    Console.WriteLine(e.CreatedBy);
                }
            }
        }
        Console.Read();
    }

    public class Account
    {
        public String CreatedBy
        {
            get;
            set;
        }

    }
static void Main()
{           
绑定b=新绑定();
b、 AddBind(“CreatedBy”、“Create_by”);
使用(var Conn=new OracleConnection())
{
Conn.ConnectionString=od.Options.GetConnectionString();
使用(var命令=新OracleCommand())
{
Command.Connection=Conn;
Command.CommandText=“从帐户中选择*”;
Conn.Open();
var a=命令绑定(b);
foreach(a账户中的e账户)
{
Console.WriteLine(e.CreatedBy);
}
}
}
Console.Read();
}
公共类帐户
{
创建的公共字符串
{
得到;
设置
}
}

作为一种稍微好一点的方法,您可以像Telerik那样指定绑定属性:使用Linq表达式。这是用法。而不是:

AddBind("CreatedBy", "Created_by");
你会写信吗

AddBind( x => x.CreatedBy, "Created_by");
你会得到一个稍微强一点的打字机会。
AddBind
的签名为:

public void AddBind<T>(Expression<Func<Account, T>> variable, string columnName) {
    // ...
}

我把从表达式中挖掘属性描述符的问题留给您作为练习:)

好吧,使用ORM?您不需要重新发明轮子。
有没有更好的方法将对象从数据库查询映射到对象?
-是的,它被称为。我每天都在网上看到很多类似的问题,这让我觉得微软并没有宣传它是很好的。同意,ORM是一条出路。您可以使用EF NHibernate,这是另一个很好的选择。如果数据总是相同的,并且来源不同,那么EF或NHibernate仍然可以正常工作。您只需要动态地传入连接字符串,而不是在app/web.config中硬编码或将其作为变量。
public void AddBind(Expression<Func<Account, double>> variable, string columnName) {
    // Add binding for double
}

public void AddBind(Expression<Func<Account, DateTime>> variable, string columnName) {
    // Add binding for DateTime
}

// ...
class BindingMap<BusinessClass> {
  // ....

    public void AddBind(Expression<Func<BusinessClass, double>> variable, string columnName) {
        // Add binding for double
    }

    public void AddBind(Expression<Func<BusinessClass, DateTime>> variable, string columnName) {
        // Add binding for DateTime
    }

    // ... 
};