Using LINQ to SQL with MS Access databases
As you probably know the LINQ to SQL functionality in .NET 3.5 is only supported with SQL Server databases, as the SQL commands generated by the DataContext are targetted at SQL Server.
However the DataContext does not enfore it's connection to be a SQL server connection, and you can in fact pass an OleDbConnection object. I personally find Access very capable for some projects - so obviously it makes sense to be able to use LINQ to SQL with Access databases. Searching on this topic returns very little info, especially since most articles refer to "data access layer".
Anyway - if you have classes decorated with the [Column] attributes etc corresponding to your tables, you CAN in fact query the Access database with LINQ queries. I'm not saying *all* LINQ queries will work - I am still to test how many. But many types should, since the Access SQL syntax flavour is not that different from SQL server's.
However what I really wanted was to be able to use the SubmitChanges() feature to push object data back to the database. Unfortunately the SQL generated by the create & update functions are NOT compatible with Access.
The INSERT gives an error of a "missing semicolon" (due to a second query to retrieve the identity value), and the UPDATE gives an error saying "row not found or changed" (the reason still eludes me, after seeing the query it generates).
The solution is to create a class that inherits from DataContext, and implement Update & Insert methods that it will call instead. If you use a customisable data-layer generator, this class can be automated. Basically you need to execute custom INSERT & UPDATE queries. If you follow this format you could save yourself a lot of time and banging-head-against-desk:
Now you should be able to create/update rows the usual LINQ way:
-------------
Customer newCust = new Customer() { Name = "n", Description = "d" };
db.Customers.InsertOnSubmit(newCust);
try
{
db.SubmitChanges();
}
catch (Exception err)
{
MessageBox.Show(err.Message);
}
MessageBox.Show(newCust.ID.ToString());
-------------
Here is the full code for the DataContext-inherited class:
[System.Data.Linq.Mapping.Provider(typeof(System.Data.Linq.SqlClient.Sql2000Provider))]
[System.Data.Linq.Mapping.DatabaseAttribute()]
public partial class Db : System.Data.Linq.DataContext
{
void UpdateCustomer(Customer c)
{
this.ExecuteCommand("UPDATE [Customers] SET [Name]=@p1, [Description]=@p2, [Version]=@p3 WHERE [ID]=@p0", c.ID, c.Name);
}
void InsertCustomer(Customer c)
{
IDbCommand cmd;
string query = "INSERT INTO [Customers] ([Name], [Description], [Version]) VALUES (@p0, @p1, @p2)";
cmd = this.Connection.CreateCommand();
cmd.Transaction = this.Transaction;
cmd.CommandText = query;
cmd.Parameters.Add(new OleDbParameter("p0", c.Name));
cmd.Parameters.Add(new OleDbParameter("p1", c.Description));
cmd.Parameters.Add(new OleDbParameter("p2", c.Version));
cmd.ExecuteNonQuery();
cmd = this.Connection.CreateCommand();
cmd.Transaction = this.Transaction;
cmd.CommandText = "SELECT @@IDENTITY";
c.ID = Convert.ToInt32(cmd.ExecuteScalar());
}
private static System.Data.Linq.Mapping.MappingSource mappingSource = new AttributeMappingSource();
public Db() :
base(global::LinqExp1.Properties.Settings.Default.cnwin_mainConnectionString, mappingSource)
{
OnCreated();
}
public Db(string connection) :
base(connection, mappingSource)
{
OnCreated();
}
public Db(System.Data.IDbConnection connection) :
base(connection, mappingSource)
{
OnCreated();
}
public Db(string connection, System.Data.Linq.Mapping.MappingSource mappingSource) :
base(connection, mappingSource)
{
OnCreated();
}
public Db(System.Data.IDbConnection connection, System.Data.Linq.Mapping.MappingSource mappingSource) :
base(connection, mappingSource)
{
OnCreated();
}
void OnCreated()
{ }
public System.Data.Linq.Table Customers
{
get
{
return this.GetTable();
}
}
}
However the DataContext does not enfore it's connection to be a SQL server connection, and you can in fact pass an OleDbConnection object. I personally find Access very capable for some projects - so obviously it makes sense to be able to use LINQ to SQL with Access databases. Searching on this topic returns very little info, especially since most articles refer to "data access layer".
Anyway - if you have classes decorated with the [Column] attributes etc corresponding to your tables, you CAN in fact query the Access database with LINQ queries. I'm not saying *all* LINQ queries will work - I am still to test how many. But many types should, since the Access SQL syntax flavour is not that different from SQL server's.
However what I really wanted was to be able to use the SubmitChanges() feature to push object data back to the database. Unfortunately the SQL generated by the create & update functions are NOT compatible with Access.
The INSERT gives an error of a "missing semicolon" (due to a second query to retrieve the identity value), and the UPDATE gives an error saying "row not found or changed" (the reason still eludes me, after seeing the query it generates).
The solution is to create a class that inherits from DataContext, and implement Update & Insert methods that it will call instead. If you use a customisable data-layer generator, this class can be automated. Basically you need to execute custom INSERT & UPDATE queries. If you follow this format you could save yourself a lot of time and banging-head-against-desk:
Now you should be able to create/update rows the usual LINQ way:
-------------
Customer newCust = new Customer() { Name = "n", Description = "d" };
db.Customers.InsertOnSubmit(newCust);
try
{
db.SubmitChanges();
}
catch (Exception err)
{
MessageBox.Show(err.Message);
}
MessageBox.Show(newCust.ID.ToString());
-------------
Here is the full code for the DataContext-inherited class:
[System.Data.Linq.Mapping.Provider(typeof(System.Data.Linq.SqlClient.Sql2000Provider))]
[System.Data.Linq.Mapping.DatabaseAttribute()]
public partial class Db : System.Data.Linq.DataContext
{
void UpdateCustomer(Customer c)
{
this.ExecuteCommand("UPDATE [Customers] SET [Name]=@p1, [Description]=@p2, [Version]=@p3 WHERE [ID]=@p0", c.ID, c.Name);
}
void InsertCustomer(Customer c)
{
IDbCommand cmd;
string query = "INSERT INTO [Customers] ([Name], [Description], [Version]) VALUES (@p0, @p1, @p2)";
cmd = this.Connection.CreateCommand();
cmd.Transaction = this.Transaction;
cmd.CommandText = query;
cmd.Parameters.Add(new OleDbParameter("p0", c.Name));
cmd.Parameters.Add(new OleDbParameter("p1", c.Description));
cmd.Parameters.Add(new OleDbParameter("p2", c.Version));
cmd.ExecuteNonQuery();
cmd = this.Connection.CreateCommand();
cmd.Transaction = this.Transaction;
cmd.CommandText = "SELECT @@IDENTITY";
c.ID = Convert.ToInt32(cmd.ExecuteScalar());
}
private static System.Data.Linq.Mapping.MappingSource mappingSource = new AttributeMappingSource();
public Db() :
base(global::LinqExp1.Properties.Settings.Default.cnwin_mainConnectionString, mappingSource)
{
OnCreated();
}
public Db(string connection) :
base(connection, mappingSource)
{
OnCreated();
}
public Db(System.Data.IDbConnection connection) :
base(connection, mappingSource)
{
OnCreated();
}
public Db(string connection, System.Data.Linq.Mapping.MappingSource mappingSource) :
base(connection, mappingSource)
{
OnCreated();
}
public Db(System.Data.IDbConnection connection, System.Data.Linq.Mapping.MappingSource mappingSource) :
base(connection, mappingSource)
{
OnCreated();
}
void OnCreated()
{ }
public System.Data.Linq.Table
{
get
{
return this.GetTable
}
}
}
19 Comments:
Ok, but how to generate the .dbml file for ms access (.mdb) file?
By telematicsPL, at 5:51 am
Visit www.blsys.net there is an open source projet and a tutorial to us LinQ 2 MS Access. The project is preliminary but very simple to use.
By Martin Duhalde, at 6:11 am
Thanks, your post helped me!!!
I can insert new records but I CANNOT update existing records.
I copied your code with customizations to my needs, everything seems OK. When I do an update, values do not change. There are no exceptions raised. Here is how I do update:
var y = from e in db.AccessDataContext.Employees
where e.Account.Contains("az")
select e;
Employee[] emps = y.ToArray();
if(emps != null) emps[0].LastName = "newValue";
By Bazi, at 11:32 pm
Of course, I do this in the end:
db.AccessDataContext.SubmitChanges();
By Bazi, at 11:35 pm
Today I woke up and saw that some data on my PC were damaged.Fortunately I could recover mdb files with help-Recovery for Access.Moreover tool made it for free and demonstrated how it working with source files having *.mdb and *.accdb extensions.
By Alex, at 1:51 pm
Manolo Blahnik Feather T-Strap Sandal
Manolo Blahnik Knotted Slingback Sandal
Manolo Blahnik Leopard Crisscross Sandals
christian louboutin Alta Bouton Ankle Boots
Christian Louboutin Ariella studded boots
By jimmychooshoes, at 8:27 am
Nice piece of work.
However I got the Update part not working in your approach. If I do it differently it works:
this.ExecuteCommand(string.Format("UPDATE Sites SET [Description]='{1}' WHERE [ID]={0}", c.ID, c.Description), "");
By frank, at 5:53 am
Nice article but I am wondering how do you generate the dbml for the access database.
By Tad, at 2:42 am
Very helpful post, many thanks.
I'm using LinqToSQL with MS Access and was also having a problem with the update method.
I solved it by declaring the parameters in the order in which they appear in the query (anything else didn't work).
And by making sure that text values were specified as auto generated in the dbml file, otherwise I got an exception for null references.
By yuominae, at 8:06 pm
ixnay2infinity
Here is a LINQ Provider for MS Access:
https://www.kellermansoftware.com/p-47-net-data-access-layer.aspx
By darichkid, at 9:33 am
zhengjx20160518
louis vuitton handbags
coach factory outlet
kobe 8
michael kors outlet
louis vuitton handbags
cheap oakleys
louis vuitton outlet online
cheap jordan shoes
michael kors outlet
louis vuitton outlet
polo ralph lauren outlet
louis vuitton outlet
michael kors outlet
designer handbags
michael kors handbags
coach factory outlet
cheap basketball shoes
cheap air jordans
michael kors handbags
coach outlet
supra for sale
christian louboutin sale
coach outlet
nike air max uk
coach factory outlet online
michael kors bags
louis vuitton handbags
fitflop clearance
coach outlet
pandora charms
adidas yeezy
gucci outlet online
ray bans
longchamp outlet
replica rolex watches
louis vuitton purses
retro jordans 13
true religion jeans
michael kors outlet clearance
christian louboutin outlet
By Unknown, at 8:21 pm
I have got more information about ms access database to SQL. Valuable details.
Microsoft Access to SQL Server Migration
By Unknown, at 4:08 am
Mobdro is a free variation hatenablog.com streaming App where you can appreciate all the cost-free Click Here videos, Movies, as well as Tv Shows. Mobdro Application mobdro has been launched for the Android individuals. Mobdro APK Download There are 2 various version of mobdro apk are available download mobdro one of them is paid.
By lindaatkinson, at 1:57 am
Creehack contains sitey.me/ an integrated Free Card that allows official guide you to buy all the Premium features CreeHack Android Install, Download on Android Free from Google Play shop free of charge there CreeHack APK are numerous other functions of Creehack Pro that CreeHack you will undoubtedly enjoy for your Android Device.
By lindaatkinson, at 5:08 am
شحن عفش
نقل العفش
شركة تنظيف
عزل اسطح
مكافحة حشرات بالرياض
مكافحة الحشرات المنزلية
By Unknown, at 11:13 am
نقل الاثاث
نقل الاثاث
نقل الاثاث
شحن عفش
شحن عفش
شحن عفش
By Unknown, at 11:22 am
تنظيف منازل
نقل العفش
مكافحة الحشرات المنزلية
رش مبيدات
اجهزة كشف التسربات
غسيل خزانات المياه
By Unknown, at 11:31 am
moncler
oakley sunglasses cheap
adidas uk
marc jacobs
moncler
ray ban sunglasses
moncler jackets
tods
ray ban sunglasses
pandora
2018.1.15xukaimin
By chenmeinv0, at 12:03 am
www0528
canada goose jackets
prada handbags
nba jerseys
tory burch outlet
nike presto
canada goose outlet
undefeated clothing
christian louboutin outlet
jerseys from china
nike factory outlet
By Unknown, at 12:46 am
Post a Comment
<< Home