In LinqPad how to discard/clear all pending changes to database, LinqToSql DataContext does not have a method - linq-to-sql

Using the amazing LinqPad. Is there a way to clear all pending database changes to the built-in LinqToSql DataContext (the UserQuery object which is this)?
Example LinqPad file, connection to a basic mssql database with tb_person table.
void Main()
{
var newRow = new tb_person() {FirstName = "Bob"};
// do lots of db updates, deletes, inserts....
tb_persons.InsertOnSubmit(newRow);
// how to do this, revert all pending Db changes?
//this.SomeMethodToDiscardChanges()
}
I found 2 option, neither seems to be ideal, maybe there is a LinqPad specific way outside of LinqToSql?
Create a new DataContext, how to do this in LinqPad?
DataContext.Refresh() method passing in every added or changed entity, cumbersome!
References
How to clear the DataContext cache on Linq to Sql

No guarantees, but you can try
this.Uncapsulate().ClearCache();
I've used this and it seems to work, but I've never used it on a production database.
Alternatively, you can create a new DataContext using
var dc = new TypedDataContext(this.Connection.ConnectionString);
but of course you can't assign to this which means that you need to be careful to prefix all your queries and references to use dc.

Related

Symfony2 and Doctrine Mysql Test Database Persist

I have a basic OneToMany relationship between an Administratorand Role.
The owning side is Administrator:
/**
* #ORM\OneToMany(targetEntity="App\PublicBundle\Entity\Role", mappedBy="administrator", cascade="persist")
**/
private $roles;
public function __construct() {
$this->roles = new ArrayCollection();
}
The inverse side is Role.
/**
* #ORM\ManyToOne(targetEntity="App\PublicBundle\Entity\Administrator", inversedBy="roles")
* #ORM\JoinColumn(name="admin_id", referencedColumnName="admin_id")
**/
private $administrator;
The Administrator can have many Roles like ROLE_ADMIN or ROLE_USER.
The code to save them atomically is...
$administrator = new Administrator();
$administrator->setName('Mario');
$administrator->setLastname('Superman');
$administrator->setUsername('mario#gmail.com');
$administrator->setPassword('password');
$role_admin = new Role();
$role_admin->setRole('ROLE_ADMIN');
$role_admin->setAdministrator($administrator);
$role_user = new Role();
$role_user->setRole('ROLE_USER');
$role_user->setAdministrator($administrator);
$administrator->setRoles($role_admin);
$administrator->setRoles($role_user);
$em->persist($administrator);
$em->persist($role_user);
$em->persist($role_admin);
$em->flush();
Basic stuff. This code is inside a Symfony2 controller that is called via Ajax. It throws an Integrity constraint violation where he says that he cannot put null in admin_id column beacuse it is null. It also emmits two notices that say undefined index role_id.
The strange stuff is that the rows are not saved but the admin_id on the administrators table gets incremented.
The even stranger stuff is that I have a UnitTest that does the same thing (literally the same thing with the same code) and persists the entities.
So how code test code work but the same code in the live controller doesn't?
EDIT: I call the controller via Ajax and it doesn't get persisted but if I go straight to the url that make a request with ajax, it gets persisted two times. Ones for the ajax post request and the second when i go straight to link on the browser. Am I missing something basic here beacuse I have a feeling that I am.
The answer is that my database was named as test_suite what mysql regarded as a test database. I don't know the details but it seems that every database that has test_ like names is regared by mysql in special rules. As I said, i don't know the details but I couldn't make a transactional insert statement in that kind of database.
When I created a new database called suit, everything worked.
This blog post
doesn't say that transactional insert statements are prohibited in test databases, but it seems that it is a bad idea to name your database test_ like. I didn't know that and had to learn it the hard way

Can I "undo" a LINQ to SQL update?

In LINQ-to-SQL if I update an object in the context but haven't called SubmitChanges, is there a way to "undo" or abandon that update so that the changes won't get submitted when I eventually call SubmitChanges?
For example, if I've updated several objects and then decide I want to abandon the changes to one of them before submitting.
Part 2: same question for Entity Framework, v3.5
Both LINQ to SQL and Entity Framework will use the same call (assuming you still have the active Context):
_dbContext.Refresh(RefreshMode.OverwriteCurrentValues, yourObj);
A more appropriate way would be to treat the Context as a Unit of Work, in which case you would no longer have an active context when refreshing the object. You would simply dispose of the object you're using currently and get a fresh copy from a new context.
I think you can use the .GetOriginalEntityState(yourEntity) to retrieve the original values. Then set your updated entity back to the original
dim db as new yourDataContext
//get entity
dim e1 as yourEntity = (from x in db.table1).take(1)
//update entity
e1.someProperty = 'New Value'
//get original entity
dim originalEntity = db.table1.getOrignalEntityState(e1)
e1 = originalEntity
db.submitChanges()
Very pseudo-code but I think it conveys the right idea. Using this method, you could also just undo one or more property changes without refreshing the entire entity.

How can I control the creation of database indexes when using DataContext.CreateDatabase()

I am new to LINQ to SQL, but have done a lot of database development in the past.
The software I just started working on uses:
// MyDataContext is a sub class of DataContext, that is generated with SqlMetal
MyDataContext db = new MyDataContext (connectionString);
db.CreateDatabase();
to create the database when it is first run.
I need to add some indexes to the tables....
How can I tell the DataContext what indexes I want?
Otherwise how do I control this?
(I could use a sql script, but I like the ideal that db.CreateDatabase will always create a database that matches the data access code)
(For better, or worse the software has full access to the database server and our software often create databases on the fly to store result of model runs etc, so please don’t tell me we should not be creating databases from code)
I seem not to be the only person hitting limts on DataContext.CreateDatabase() see also http://csainty.blogspot.com/2008/02/linq-to-sql-be-careful-of.html
As far as I know the DataContext.CreateDatabase method can only create primary keys.
When you look at the DBML directly, you will see that there are no elements for defining an index. Therefore it is, IMHO, save to assume that CreateDatabase cannot do it.
So the only way I can think of for creating indexes "automatically" is by first calling DataContext.CreateDatabase and then calling DataContext.ExecuteCommand to add the indexes to the tables that were just created.
You can execute SQL Command on DatabaseCreated method.
public partial class DatabaseModelsDataContext : System.Data.Linq.DataContext
{
partial void OnCreated ()
{
var cmdText = #"
IF EXISTS (SELECT name FROM sys.indexes WHERE name = N'IX_LeafKey')
DROP INDEX IX_MyTableColumn
ON [mydb].[dbo].[Leaf];
CREATE INDEX IX_MyTableColumn
ON [mydb].[dbo].[MyTable] ([column]) ;";
ExecuteCommand(cmdText);
}
}

Linq to Sql Update not persisting to the Database

I have a standard update happening via linq to sql but the data does not persist to the database.
I am using an auto-generated class via the .dbml file designer.
The update statement is below:
public static void UpdateEmailsInWorkingTable(Guid emailGuid, string modifiedEmail)
{
using (EmailDBDataContext DBContext = new EmailDBDataContext())
{
EmailAddress_Update EAUpdated = (from e in DBContext.EmailAddress_Updates
where e.EmailGuid == emailGuid
select e).SingleOrDefault();
EAUpdated.EmailAddress = modifiedEmail;
EAUpdated.IsValid = 'Y';
EAUpdated.UpdateFlag = true;
EAUpdated.LastChangedDtTm = DateTime.Now;
try
{
DBContext.SubmitChanges(ConflictMode.FailOnFirstConflict);
}
catch (ChangeConflictException ex)
{
// do stuff here
}
}
}
I looked through my auto-generated DataContext class and the only glaring difference is that the table in question EmailAddress_Update does not implement the two interfaces INotifyPropertyChanging and INotifyPropertyChanged that the other auto-generated entities do.
I am assuming that this is the cause of why the changes are not being persisted is it not???
To put it simply none of the Extensibility Method Definitions get generated for any part of this one class. If this is the cause of my problems, what in the database would be causing this to not auto-generate properly??
Thanks~
I posted this question on MSDN as well here: MSDN Linq to Sql if you wanted to see the replies. But I found part of the reason why the code doesn't generate.
Here is a piece from my MSDN response:
I created a small test table without a primary key and added it to the designer and sure enough it didn't generate any of the Extensibility methods for that instance.
So I then added a primary key to the same table and re-added it to the designer and sure enough all of the extensibility methods and change tracking events were generated.
My question now is why must there be a primary key for this stuff to auto-generate?
Ok so to answer my own question "My question now is why must there be a primary key for this stuff to auto-generate?" I found it in the book Pro LINQ written by Joe Joseph C. Rattz, Jr.
I was reading how to handle views versus tables and he says this:
"Because the entity classes generated for views do not contain entity class properties that are mapped as primary keys, they are read-only. If you consider that without primary keys, the DataContext has no effective way to provide identity tracking, this makes sense."
Mystery and problem solved.

DLINQ- Entities being inserted without .InsertOnSubmit(...)?

I ran into an interesting problem while using DLINQ. When I instantiate an entity, calling .SubmitChanges() on the DataContext will insert a new row into the database - without having ever called .Insert[All]OnSubmit(...).
//Code sample:
Data.NetServices _netServices = new Data.NetServices(_connString);
Data.ProductOption[] test = new Data.ProductOption[]
{
new Data.ProductOption
{
Name="TEST1",
//Notice the assignment here
ProductOptionCategory=_netServices.ProductOptionCategory.First(poc => poc.Name == "laminate")
}
};
_netServices.SubmitChanges();
Running the code above will insert a new row in the database. I noticed this effect while writing an app to parse an XML file and populate some tables. I noticed there were 1000+ inserts when I was only expecting around 50 or so - then I finally isolated this behavior.
How can I prevent these objects from being persisted implicitly?
Thanks,
-Charles
Think of the relationship as having two sides. When you set one side of the relationship the other side needs to be updated so in the case above as well as setting the ProductOptionCategory it is effectively adding the new object to the ProductOptions relationship on the laminate ProductOptionCategory side.
The work-around is as you have already discovered and to set the underlying foreign key instead so LINQ to SQL will not track the objects in the usual way and require implicit indication it should persist the object.
Of course the best solution for performance would be to determine from the source data which objects you don't want to add and never create the instance in the first place.