I am in search of an good approach to import data from ms access and bind it to any Model of an MVC pattern
Here is the approach which we are thinking to following
Approach 1 :
Open Ms Access file
Open database
Open all tables
Import data of all tables and bind them to an model
Close all tables
Close database
Close file
Approach 2 :
Connect Ms Access Database in Asp.Net MVC
Open the database
pass an query
fetch data and bind it to model
close database
Which approach is better and how I can Implement it?
UPDATE:
I have implemented Approach 2 and its works fine , does anyone know how to implement Approach 1
Both approaches will require you to connect to your database and map the contents into your model. I'm assuming Approach 1 is 'when the web app starts connect and copy all the database contents into memory and access if from there' and Approach 2 is 'when I need to display some data, connect the the database and copy the specific contents to my model'.
If this is the case, then Approach 2 is recommended (and you've stated you have done this so all is good).
Approach 1 may work ok-ish for smaller sized databases but:
You loose all the [acid][1]-y goodness that your database provides
Your stuck with global collection variables - not the most loved concept in web apps
You have an entire database unnecessarily in memory. Your slow point in web apps is usually the network, a few milliseconds to load data when needed is nothing compared with the time it takes for your html to reach the browser
If you were to try approach one (not recommended, do not do, a kitten is harmed each time this code is run) , then the easiest way would be to have something like this in your global.asax.cs file:
public class MvcApplication : System.Web.HttpApplication {
public static List<MyTable1> globalTable1;
public static List<MyTable2> globalTable2;
protected void Application_Start() {
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
var DatabaseMagic = new DatabaseAccessClass("a:\path\to\database.mdb");
globalTable1 = DatabaseMagic.getDataForTableOne(); //However you do your loading and mapping
globalTable2 = DatabaseMagic.getDataForTableTwo(); //ditto
}
Then in your controllers:
public ActionResult Index()
{
return View(MvcApplication.globalTable1);
}
And your view:
#model List<MvcApplication1.MvcApplication.MyTable1>
#{
ViewBag.Title = "Index";
}
<h2>Blah</h2>
<ul>
#foreach (var i in Model) {
<li>#i.idField - #i.contentField </li>
}
</ul>
(Did I mention don't do this?)
Use Entity Framework.Create ViewModel to map.
What you should do is build your model according to your table. So the model class should have properties which correspond to your table fields. Then when you require the Model you would query againist the DB and populate the model's properties accordingly.
I did not understood Approach 1.
Is it a requirement to use Access? I have seen there are lot of problems with file based database (such as Access) so better import all the data to SQL Server or some other database from Access and then use option 2.
As your database already created you can use Entity Framework database first approach to bind it.
You need to add using System.Data.OleDb; in Header file
And add these Provider=Microsoft.ACE.OLEDB.12.0;DataSource=|DataDirectory|\myAccessFile.mdb;
Persist Security Info=False; line in connection string use connection string fetch
update ms-access database using OleDbCommand , OleDbConnection
and ms-access query just like sql query
Related
Is there actually any official strategy for creating and using views with EF6.1 Code First? I can reverse the database into Code First and get tables not views. I can import the database into Model First and get views and then do Generate DB from Model and my edmx is modified and the views are converted to tables. MSFT seems to have all but abandoned Model First, and the new Update 2 seems to have reverse engineering for Code First so I feel forced to convert to Code First but has the EF team given support for any reasonable approach to using views or stored Procedures in Code First? After all CF is supposed to create the DB but what - are you no longer supposed to use either of these SQL Server features in a .NET EF application?
For starters you can use views and stored procedures that are already created in the database. For views you don't have to do any mapping if you create a code like this:
public TestContext : DbContext
{
public DbSet<User> AdminUsers { get; set; }
}
And you have a view in the database named dbo.AdminUsers and it can be mapped to the class User (contains all required properties with the same name as the property).
For stored procedures you can use the SqlQuery function either through the Database property of the DbContext such as:
var userActivityReport = context.Database.SqlQuery<UserActivityReport>(
"dbo.GetUserActivityReport #p0, #p1", startDate, endDate);
Or through the SqlQuery function of the DbSet class:
var newUsers = context.Users.SqlQuery("dbo.GetNewUsers #p0", count);
If you want to create, modify or delete views and stored procedures via Entity Framework you can either use custom migration operations see http://dolinkamark.wordpress.com/2014/05/03/creating-a-custom-migration-operation-in-entity-framework/
For event better integration you can use the Public mapping API with a library provided by a community member: https://codefirstfunctions.codeplex.com/
In the application I'm building the very first thing the client does is request the breeze metadata. If the database does not exist and entity framework needs to create the database it will not seed using the initializer configured with Database.SetInitializer.
If something else triggers EF to do a query against the dbcontext first then the database is seeded as expected.
I'm not sure if this is a bug or intended for some reason?
Thanks
I'm pretty sure the bug is on your end. I have no trouble retrieving metadata first at which point the database is created and seeded. Do it all the time.
You can see this for yourself in any of the Breeze Todo samples. Remember that your first Breeze client query always asks for metadata before processing your query so the first call to the server (in these samples) is always a request for metadata. These samples would not work if a request for metadata failed to generate the database.
The Todos sample initializes and seeds the database in a trivial way in the class ctor (the static ctor). Here's the entire TodosContext.cs
namespace Todo.Models {
using System.Data.Entity;
public class TodosContext : DbContext
{
// DEVELOPMENT ONLY: initialize the database
static TodosContext()
{
Database.SetInitializer(new TodoDatabaseInitializer());
}
public DbSet<TodoItem> Todos { get; set; }
}
}
To see it in action:
Show all files
Delete the *App_Data/todo.sdf* database
Set breakpoints on that constructor and on the methods of the Web API controller.
Run with debug (F5) ... you'll see the metadata endpoint hit first, then this static constructor.
Look at the *App_Data* folder in Windows Explorer and confirm that the database was created.
Continue ... you'll see the Todos query endpoint hit.
Continue ... the screen fills with seeded todos.
How are you doing it?
I am learning MVC4 in Visual Studio and I have many questions about it. My first statement about MVC is that MVC's Model doesnt do what I expected. I expect Model to select and return the data rows according to the needs.
But I read many tutorial and they suggest me to let Model return ALL the data from the table and then eliminate the ones I dont need in the controller, then send it to the View.
here is the code from tutorials
MODEL
public class ApartmentContext : DbContext
{
public ApartmentContext() : base("name=ApartmentContext") { }
public DbSet<Apartment> Apartments { get; set; }
}
CONTROLLER
public ActionResult Index()
{
ApartmentContext db = new ApartmentContext();
var apartments = db.Apartments.Where(a => a.no_of_rooms == 5);
return View(apartments);
}
Is this the correct way to apply "where clause" to a select statement? I dont want to select all the data and then eliminate the unwanted rows. This seems weird to me but everybody suggest this, at least the tutorials I read suggest this.
Well which ever tutorial you read that from is wrong (in my opinion). You shouldn't be returning actual entities to your view, you should be returning view models. Here's how I would re-write your example:
public class ApartmentViewModel
{
public int RoomCount { get; set; }
...
}
public ActionResult Index()
{
using (var db = new ApartmentContext())
{
var apartments = from a in db.Apartments
where a.no_of_rooms == 5
select new ApartmentViewModel()
{
RoomCount = a.no_of_rooms
...
};
return View(apartments.ToList());
}
}
Is this the correct way to apply "where clause" to a select statement?
Yes, this way is fine. However, you need to understand what's actually happening when you call Where (and various other LINQ commands) on IQueryable<T>. I assume you are using EF and as such the Where query would not execute immediately (as EF uses delayed execution). So basically you are passing your view a query which has yet to be run and only at the point of where the view attempts to render the data is when the query will run - by which time your ApartmentContext will have been disposed and as a result throw an exception.
db.Apartments.Where(...).ToList();
This causes the query to execute immediately and means your query no longer relys on the context. However, it's still not the correct thing to do in MVC, the example I have provided is considered the recommended approach.
In our project, we will add a Data Access Layer instead of accessing Domain in controller. And return view model instead of Domain.
But your code, you only select the data you need not all the data.
If you open SQL Profiler you'll see that's a select statement with a where condition.
So if it's not a big project I think it's OK.
I can't see these tutorials but are you sure it's loading all the data? It looks like your using entity framework and entity framework uses Lazy laoding. And Lazy loading states:
With lazy loading enabled, related objects are loaded when they are
accessed through a navigation property.
So it might appear that your loading all the data but the data itself is only retrieved from SQL when you access the object itself.
In my application user can personalize their settings like background-image,use https etc.
How should i add these setting to users page.I mean should i store these setting like bacjground-image in session.What is the better way of dong it.I am using ASP.Net MVC.
Please help.
Maybe my answer on the question how to change the themes in asp.net mvc 2 can help you.
ASP.Net Profiles is used in such cases
There are really two options here
You can use the Profile functionality build into ASP.NET
Build your own class and then store the user settings in a table in the database
With option one there are plenty of tutorials and a good video on the ASP.NET website: http://www.asp.net/general/videos/how-do-i-customize-my-site-with-profiles-and-themes
With option two you would want to produce a user settings class which might look like this:
public class UserSettings{
public int UserId {get;set;}
public string BackgroundImage {get;set;}
public bool UserHttps {get;set;}
}
There would be a database table or some sort of persistent store the class was mapped onto. If you want to avoid a trip to the database every request you can pull an instance of the class from the database the first time the user logs in and then cache them somewhere. The cache could be the session, a cookie, the application cache etc.
I was reading Steven Sanderson's book Pro ASP.NET MVC Framework and he suggests using a repository pattern:
public interface IProductsRepository
{
IQueryable<Product> Products { get; }
void SaveProduct(Product product);
}
He accesses the products repository directly from his Controllers, but since I will have both a web page and web service, I wanted to have add a "Service Layer" that would be called by the Controllers and the web services:
public class ProductService
{
private IProductsRepository productsRepsitory;
public ProductService(IProductsRepository productsRepository)
{
this.productsRepsitory = productsRepository;
}
public Product GetProductById(int id)
{
return (from p in productsRepsitory.Products
where p.ProductID == id
select p).First();
}
// more methods
}
This seems all fine, but my problem is that I can't use his SaveProduct(Product product) because:
1) I want to only allow certain fields to be changed in the Product table
2) I want to keep an audit log of each change made to each field of the Product table, so I would have to have methods for each field that I allow to be updated.
My initial plan was to have a method in ProductService like this:
public void ChangeProductName(Product product, string newProductName);
Which then calls IProductsRepository.SaveProduct(Product)
But there are a few problems I see with this:
1) Isn't it not very "OO" to pass in the Product object like this? However, I can't see how this code could go in the Product class since it should just be a dumb data object. I could see adding validation to a partial class, but not this.
2) How do I ensure that no one changed any other fields other than Product before I persist the change?
I'm basically torn because I can't put the auditing/update code in Product and the ProductService class' update methods just seem unnatural (However, GetProductById seems perfectly natural to me).
I think I'd still have these problems even if I didn't have the auditing requirement. Either way I want to limit what fields can be changed in one class rather than duplicating the logic in both the web site and the web services.
Is my design pattern just bad in the first place or can I somehow make this work in a clean way?
Any insight would be greatly appreciated.
I split the repository into two interfaces, one for reading and one for writing.
The reading implements IDisposeable, and reuses the same data-context for its lifetime. It returns the entity objects produced by linq to SQL. For example, it might look like:
interface Reader : IDisposeable
{
IQueryable<Product> Products;
IQueryable<Order> Orders;
IQueryable<Customer> Customers;
}
The iQueryable is important so I get the delayed evaluation goodness of linq2sql. This is easy to implement with a DataContext, and easy enough to fake. Note that when I use this interface I never use the autogenerated fields for related rows (ie, no fair using order.Products directly, calls must join on the appropriate ID columns). This is a limitation I don't mind living with considering how much easier it makes faking read repository for unit tests.
The writing one uses a separate datacontext per write operation, so it does not implement IDisposeable. It does NOT take entity objects as input or out- it takes the specific fields needed for each write operation.
When I write test code, I can substitute the readable interface with a fake implementation that uses a bunch of List<>s which I populate manually. I use mocks for the write interface. This has worked like a charm so far.
Don't get in a habit of passing the entity objects around, they're bound to the datacontext's lifetime and it leads to unfortunate coupling between your repository and its clients.
To address your need for the auditing/logging of changes, just today I put the finishing touches on a system I'll suggest for your consideration. The idea is to serialize (easily done if you are using LTS entity objects and through the magic of the DataContractSerializer) the "before" and "after" state of your object, then save these to a logging table.
My logging table has columns for the date, username, a foreign key to the affected entity, and title/quick summary of the action, such as "Product was updated". There is also a single column for storing the change itself, which is a general-purpose field for storing a mini-XML representation of the "before and after" state. For example, here's what I'm logging:
<ProductUpdated>
<Deleted><Product ... /></Deleted>
<Inserted><Product ... /></Inserted>
</ProductUpdated>
Here is the general purpose "serializer" I used:
public string SerializeObject(object obj)
{
// See http://msdn.microsoft.com/en-us/library/bb546184.aspx :
Type t = obj.GetType();
DataContractSerializer dcs = new DataContractSerializer(t);
StringBuilder sb = new StringBuilder();
XmlWriterSettings settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
XmlWriter writer = XmlWriter.Create(sb, settings);
dcs.WriteObject(writer, obj);
writer.Close();
string xml = sb.ToString();
return xml;
}
Then, when updating (can also be used for logging inserts/deletes), grab the state before you do your model-binding, then again afterwards. Shove into an XML wrapper and log it! (or I suppose you could use two columns in your logging table for these, although my XML approach allows me to attach any other information that might be helpful).
Furthermore, if you want to only allow certain fields to be updated, you'll be able to do this with either a "whitelist/blacklist" in your controller's action method, or you could create a "ViewModel" to hand in to your controller, which could have the restrictions placed upon it that you desire. You could also look into the many partial methods and hooks that your LTS entity classes should have on them, which would allow you to detect changes to fields that you don't want.
Good luck! -Mike
Update:
For kicks, here is how I deserialize an entity (as I mentioned in my comment), for viewing its state at some later point in history: (After I've extracted it from the log entry's wrapper)
public Account DeserializeAccount(string xmlString)
{
MemoryStream s = new MemoryStream(Encoding.Unicode.GetBytes(xmlString));
DataContractSerializer dcs = new DataContractSerializer(typeof(Product));
Product product = (Product)dcs.ReadObject(s);
return product;
}
I would also recommend reading Chapter 13, "LINQ in every layer" in the book "LINQ in Action". It pretty much addresses exactly what I've been struggling with -- how to work LINQ into a 3-tier design. I'm leaning towards not using LINQ at all now after reading that chapter.