4

I've been trying to use a preexisting database in my ASP.NET MVC project. I create a "Data Connection" to my (Microsoft SQL)Database (".\SQLEXPRESS.Databases"), which has the table "Test". This table has two columns, "ID (int)" and "name (nvarchar(MAX))".

In the "Models" folder I put this new class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

using System.Data.Entity;

namespace MvcMovie.Models
{
    public class Test
    {
        public int ID { get; set; }
        public string name { get; set; }
    }
}

Then (in "Controllers") I have a new Controller, "HelloWorldController". In this I have this function:

    public ActionResult Index()
    {
        DataSet data;
        DataTable table;

        using (SqlConnection connection = new SqlConnection(connectionString))
        {
            connection.Open();

            SqlCommand select = new SqlCommand("SELECT * FROM Test", connection);

            SqlDataAdapter adapter = new SqlDataAdapter();
            adapter.SelectCommand = select;

            data = new DataSet();
            adapter.Fill(data, "Test");

            table = data.Tables[0]; //is the [0] really correct?
        }

        return View(/* HOW DO I GET THE TABLE TO THE VIEW? */);
    }

Now I would like to display the rows of the table in my "Index.cshtml" file (in "Views"). How do I get the table from the Controller to the view? What I found was with "@model" and "IEnumerable", but that does not work, since I cannot convert my table.

@model IEnumerable<MyProject.Models.Test>

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

@foreach (var item in Model) {
    <p>blaaaah</p>
}

Now there are three questions:
1. Am I doing something completely wrong? (Method of DB-Access,..)
2. Is there an easier way to do this? (Without all adapter,.. stuff)
3. If !1&&!2, How do I get it to work? (Get the view file to "know" my table)

Thanks for help,
Regards,
Caba

1 Answer 1

13

I'd recommend you using view models and get rid of DataSets and Tables. Let's forget about those data types. They are legacy.

For example you could have a method (which you would eventually externalize into a repositorhy to avoid polluting your controller code with database access):

public IEnumerable<Test> GetTests()
{
    using (var conn = new SqlConnection(connectionString))
    using (var cmd = conn.CreateCommand())
    {
        conn.Open();
        cmd.CommandText = "SELECT ID, name FROM Test";
        using (var reader = cmd.ExecuteReader())
        {
            while (reader.Read())
            {
                yield return new Test
                {
                    ID = reader.GetInt32(reader.GetOrdinal("ID")),
                    name = reader.GetString(reader.GetOrdinal("name")),
                }
            };
        }
    }

}

and then your controller action:

public ActionResult Index()
{
    IList<Test> tests = GetTests().ToList();
    return View(tests);
}

So far so good. Finally the corresponding strongly typed view to display the results:

@model IList<Test>
<table>
    <thead>
        <tr>
            <th>ID</th>
            <th>Name</th>
        </tr>
    </thead>
    <tbody>
        @for (var i = 0; i < Model.Count; i++)
        {
            <tr>
                <td>@Html.DisplayFor(x => x[i].ID)</td>
                <td>@Html.DisplayFor(x => x[i].name)</td>
            </tr>
        }
    </tbody>
</table>

or use the WebGrid helper if you prefer:

@model IList<Test>
@{
    var grid = new WebGrid(Model);
}
@grid.GetHtml()
Sign up to request clarification or add additional context in comments.

3 Comments

Thank you for the detailed instructions. I really like your solution. Up to now, I have never seen that "yield" ._. but that's not really an issue. I've rewritten my stuff (the changes were not that big) to match your structure and I'm pretty happy with the result. Thanks a lot.
Just a thought... I doubt if the yield return is a good thing to do. Isn't it better to return an IList<Test> instead of IEnumerable<Test>? Is there an advantage in using the yield return?
@KSK, using an iterator allows you to lazily load the data set. For example if you need to display only the first 50 rows in your view it would be a complete waste to load all the results in memory and throw them out. Obviously in my example I am iterating on all the results in the view, but in a real world application you are probably wanting to do some pagination.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.