Как правильно использовать SqlDataSource с параметрами?

1

Вот мой код, который я использую (с инструментами разработчика oracle):

<asp:SqlDataSource ID="FirstNameSQL" runat="server" ConnectionString="<%$ ConnectionStrings:UserQueries %>" ProviderName="<%$ ConnectionStrings:UserQueries.ProviderName %>" 
        SelectCommand="SELECT &quot;FIRSTNAME&quot; FROM &quot;USERS&quot; WHERE (&quot;USERNAME&quot; = '%?')">
        <SelectParameters>
            <asp:ControlParameter ControlID="UsernameLabel" Name="firstname" PropertyName="Text" Type="String" />
        </SelectParameters>
    </asp:SqlDataSource>

Я пытаюсь сделать запрос с параметром из текста метки. Но он ничего не возвращает. Может быть, мой метод извлечения данных ошибочен, что здесь:

DataView dv4 = (DataView)FirstNameSQL.Select(DataSourceSelectArguments.Empty);
    foreach (DataRow r in dv4.Table.Rows)
    {
        FirstNameLabel.Text = (string)r[0];
    }

Какие-либо предложения?

  • 0
    Почему вы используете SqlDataSource ? Вам следует использовать OracleCommand если вы просто хотите извлечь данные из базы данных Oracle в DataView.
  • 0
    Ваш вопрос частично вдохновил меня на запись в блоге .
Теги:
sqldatasource

1 ответ

0

Вместо использования SqlDataSource для программного извлечения данных вы должны использовать класс OracleCommand. SqlDataSource следует использовать только в том случае, если вы привязываетесь непосредственно к GridView или другому GridView управления. Действительно, SqlDataSource не следует использовать вообще, поскольку доступ к данным не должен происходить на уровне пользовательского интерфейса в правильно разработанной системе.

Использование официального пакета Oracle NuGet.

public static DataTable GetDataTable(OracleCommand command)
{
    DataTable dt = new DataTable();
    using (var connection = GetDefaultOracleConnection())
    {
        command.Connection = connection;
        connection.Open();
        dt.Load(command.ExecuteReader());
    }
    return dt;
}

public static OracleConnection GetDefaultOracleConnection()
{
    return new OracleConnection(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString); //just get a connection string from somewhere
}

//usage
var command = new OracleCommand("select firstname from users where username=:username");
command.Parameters.Add("username", UsernameLabel.Text.Trim());
command.BindByName = true; //incredibly important if more than one parameter
var dt = GetDataTable(command);
DataView dv = dt.AsDataView();

//now get the results. I prefer getting it from the DataTable instead of DataView. Easier to use Linq
if(dt.Rows.Count > 0)
{
    /* Below line requires extra reference to System.Data.DataSetExtensions */
    FirstNameLabel.Text = dt.AsEnumerable().First().Select(r => r.Field<string>("firstname"));
}
else
{
    FirstNameLabel.Text = "not found";
}

Вышеприведенное должно было показать вам, как вы можете получать данные из базы данных программно. Но он по-прежнему не соответствует хорошей архитектуре, потому что мы использовали код доступа к базе данных в нашем коде. Наш код не должен иметь понятия о деталях реализации базы данных. Так что давайте начнем с нуля и создадим это немного лучше. Во-первых, мы должны определить класс, содержащий детали пользователя. Я буду называть его ApplicationUser поэтому мы не конфликтуем с свойством Page.User.

public class ApplicationUser
{
    public string Username {get; set;}
    public string FirstName {get; set;}
    public string LastName {get; set;}
}

Это круто, теперь мы определили, что нам нужно для нашего ApplicationUser. Но нам также нужен способ загрузки пользователей из базы данных. Это не должно происходить в нашем коде или в нашей модели, но это должно произойти в слое данных.

public class MySiteOracleRepository
{
    private string ConnectionString {get; set;}

    public MySiteOracleRepository(string connectionString)
    {
        ConnectionString = connectionString;
    }

    public ApplicationUser GetUserByUsername(string username)
    {
        OracleCommand command = new OracleCommand("select firstname, lastname, username from users where username=:username");
        DataTable dt = OracleDatabaseHelper.GetDataTable(command, ConnectionString);
        ApplicationUser user = dt.AsEnumerable().Select(r => new ApplicationUser(){
            FirstName = r.Field<string>("firstname"),
            LastName = r.Field<string>("lastname"),
            Username = r.Field<string>("username")
        }).Single();
        return user;
    }
}

Это хорошо. Теперь нам нужно реализовать OracleDatabaseHelper.GetDataTable() который будет выполнять фактический доступ к нашей базе данных.

public class OracleDatabaseHelper
{
    public static DataTable GetDataTable(OracleCommand command, string connectionString)
    {
        DataTable dt = new DataTable();
        using (var connection = new OracleConnection(connectionString))
        {
            command.Connection = connection;
            connection.Open();
            dt.Load(command.ExecuteReader());
        }
        return dt;
    }
}

Теперь, что это дает нам? Легкий и многоразовый способ получения информации о пользователях. Поскольку у нас есть этот код, нам не нужно повторять каждый раз, когда нам нужно получить информацию о пользователе, следуя принципу DRY (не повторяйте себя). Поэтому давайте посмотрим, как выглядит наш код страницы.

private MySiteOracleRepository repo {get; set;}

protected void Page_Load(object sender, EventArgs e)
{
    repo = new MySiteOracleRepository(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString);

    if(!IsPostBack)
    {
        LoadUserInfo();
    }
}

protected void LoadUserInfo()
{
    ApplicationUser user = repo.GetUserByUsername(UsernameLabel.Text);
    FirstNameLabel.Text = user.FirstName;
    LastNameLabel.Text = user.LastName;
}

Посмотрите, насколько простой стала наша страница? И обратите внимание, что было бы довольно легко написать новый MySiteMySqlRepository, MySitePostgresRepository, MySiteMongoRepository т.д., И вам нужно было бы действительно создать новый класс. Вам нужно будет изменить свою страницу, чтобы использовать разные типы репозиториев, но эту проблему можно решить с помощью Injection Dependency. Но я не буду вдаваться в это здесь, потому что я, вероятно, нахожусь в достаточном количестве новых вещей у вас, как есть.

  • 0
    Я добавил пакет NuGet, но уже в начале класс OracleCommand не распознается, так как он говорит: тип или пространство имен не может быть найдено Кстати, спасибо за отличное объяснение
  • 0
    @ kisbovan93 Каждый раз, когда вы получаете такую ошибку, это означает, что вам нужно добавить оператор using, чтобы привести пространство имен в область видимости. Если вы используете Visual Studio, он может сделать это автоматически. Щелкните правой кнопкой мыши код с ошибкой и перейдите к Разрешить и выберите там вариант. Если вы не используете VS, то я считаю, что вам нужно добавить using Oracle.ManagedDataAccess.Client;
Показать ещё 5 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню