LINQ to SQL - Insert New Record - linq-to-sql

I have a database table with an auto-incrementing ID field. this table is exposed to by code via a Entity Data Model. I am trying to write a new record to this table. I have a method that needs to be responsible for creating these records. This method takes in the property values of the record. It needs to create a record, and write a reference record in another table. Currently, here is what I am trying
public int CreateRecord(string name, string description, List<int> ids)
{
using (DatabaseContext database = new DatabaseContext())
{
Record record = new Record();
record.Name = name;
record.Description = description;
database.Records.InsertOnSubmit(record);
database.SubmitChanges();
List<RecordTrack> tracks = new List<RecordTrack>();
foreach (int id in ids)
{
RecordTrack track = new RecordTrack();
track.RecordID = record.ID;
track.ID = id;
tracks.Add(track);
}
database.Tracks.InsertAllOnSubmit(tracks);
database.SubmitChanges();
}
}
I can't seem to get the record to save in this manner. I was able to do it when I passed a Record in that I wanted to insert. But due to other factors, I need a way to purely create the record here from scratch. What am I doing wrong?
Thank you!

there should be a AddToRecord() function in your database context. Use that function to add your record variable and then call SaveChanges() from your database context.

Related

Why is persist in JPA clearing the existing data in the table row?

I am trying to update data to a mySQL database using JPA. I have no problem persisting data but flush will not work as expected. I retrieve the id for the login session, set that id (it is the primary key) along with setting the description field that I want merged to the database. I have debugged line by line through this method and all variables contain the expected values. Any ideas or suggestions to overcome this problem are appreciated.
public String update() {
factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
EntityManager em = factory.createEntityManager();
if(true){
em.getTransaction().begin();
String sessionEmail=Util.getEmail();
//Create query to find user passwords matching the inputted name
Query myQuery = em.createQuery("SELECT u FROM BusinessAccount u WHERE u.email=:email");
myQuery.setParameter("email", sessionEmail);
List<BusinessAccount> accounts=myQuery.getResultList();
int intId=accounts.get(0).getId();
businessAccount.setId(intId);
String des=businessAccount.getDescription();
businessAccount.setDescription(des);
em.flush();
addMessage(new FacesMessage(FacesMessage.SEVERITY_INFO,
"User Registration Successful!", null));
return "success";
}
else {
addMessage(new FacesMessage(FacesMessage.SEVERITY_ERROR,
"User Registration Failed!", null));
return "failure";
}
}
merge() persists all the state of the entity. Not just the non-null fields. I it wasn't, you would complain that you want to set some field to null and that merge() ignores it and leaves it as is.
So get an entity from the database, and modify it, instead of only gettings its ID, creating a new entity instance from scratch and only settings some of its fields.
Note that, if you get the entity and modify it inside a single transaction, you don't even have to call merge(): the new state will be made persistent automatically.

How to get the auto-increment primary key value in MySQL using Hibernate

I'm using Hibernate to access MySQL, and I have a table with an auto-increment primary key.
Everytime I insert a row into the table I don't need to specify the primary key. But after I insert a new row, how can I get the relative primary key immediately using hibernate?
Or I can just use jdbc to do this?
When you save the hibernate entity, the id property will be populated for you. So if you have
MyThing thing = new MyThing();
...
// save the transient instance.
dao.save(thing);
// after the session flushes, thing.getId() should return the id.
I actually almost always do an assertNotNull on the id of a persisted entity in my tests to make sure the save worked.
Once you're persisted the object, you should be able to call getId() or whatever your #ID column is, so you could return that from your method. You could also invalidate the Hibernate first level cache and fetch it again.
However, for portability, you might want to look at using Hibernate with sequence style ID generation. This will ease the transition away from MySQL if you ever need to. Certainly, if you use this style of generator, you'll be able to get the ID immediately, because Hibernate needs to resolve the column value before it persists the object:
#Id
#GeneratedValue (generator="MY_SEQ")
#GenericGenerator( name = "MY_SEQ",
strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator",
parameters = {
#Parameter(name = "sequence_name", value = "MY_SEQ"),
#Parameter(name = "initial_value", value = "1"),
#Parameter(name = "increment_size", value = "10") }
)
#Column ( name = "id", nullable = false )
public Long getId () {
return this.id;
}
It's a bit more complex, but it's the kind of thing you can cut and paste, apart from changing the SEQUENCE name.
When you are calling a save() method in Hibernate, the object doesn't get written to the database immediately. It occurs either when you try to read from the database (from the same table?) or explicitly call flush(). Until the corresponding record is not inserted into the database table, MySQL would not allocate an id for it.
So, the id is available, but not before Hibernate actually inserts the record into the MySQL table.
If you want, you can get the next primary key independently of an object using:
Session session = SessionFactoryUtil.getSessionFactory().getCurrentSession();
Query query = session.createSQLQuery( "select nextval('schemaName.keySequence')" );
Long key = (Long) query.list().get( 0 );
return key;
Well in case of auto increment generator class, when we use the save() method it returns the primary key (assuming its id). So it returns that particular id, so you can do this
int id = session.save(modelClass);
And return id

handle transaction in Linq to sql

I am implementing the asp.net MVC web application, where i am using the Linq to Sql to manipulate the data in database. but in my one of action, i want to insert multiple table entries which are depends upon each other by referring previous insertion Id's. So i just wnat to know how to handle the transaction, like begin transaction, commit,rollback and all like in ADO.net. how to manage this. what if one of insertion get crashed in the middle of manipulation?
Note:- I am not using the Stored procedures here. I am using Lambda expressions and methods. Also these are use in different manager classes.
Example:
For Create Subject - used method in SubjectManager class to insert subject infor, that returns subject Id. within this subjectid i am inserting the let say its chapters with another method in manager class as ChapterManager. which again returns the ChapterId, on base of this chapeter Id , inserting the Topics of chapter. that again uses Topic manager same like above.in each manger class i am creating dataContext object for the same. and I am controlling all this within a single action in my controller. but worrying about the transaction management. how I can use here ?
The DataContext already includes an embedded transaction object. For example, let's say you are placing a new order for a customer. You can set up your model so that the following code updates both the Customer AND Order table with a single SubmitChanges. As long as a foreign key relationship exists between the two tables, the embedded transaction object handles both the Customer update and the Order insert in the same transaction. Using a TransactionScope object to encase a single DataContext is redundant:
using (DataContext dc = new DataContext())
{
Order order = new Order();
order.ProductID = 283564;
order.Quantity = 7;
order.OrderDate = DateTime.Now;
Customer customer = dc.Customers.Single(c => c.CustomerID == 6);
customer.LastUpdate = order.OrderDate;
customer.Orders.Add(order);
dc.SubmitChanges();
}
using(TransactionScope scope = new TransactionScope())
{
using(DataContext ctx = new MyDataContext())
{
ctx.Subject.Add(subject);
Chapter chapter = new Chapter();
chapter.SubjectId = subject.Id;
ctx.SubmitChanges();
ctx.Chapter.Add(chapter);
ctx.SubmitChanges();
scope.Complete() // if it all worked out
}
}
From the System.Transactions namespace I believe.

Generate non-identity primary key

My workplace doesn't use identity columns or GUIDs for primary keys. Instead, we retrieve "next IDs" from a table as needed, and increment the value for each insert.
Unfortunatly for me, LINQ-TO-SQL appears to be optimized around using identity columns. So I need to query and update the "NextId" table whenever I perform an insert. For simplicity, I do this during the creation of the new object:
var db = new DataContext( "...connection string..." );
var car = Car
{
Id = GetNextId<Car>( db ),
TopSpeed = 88.0
};
db.InsertOnSubmit( car );
db.SubmitChanges();
The GetNextId method is something like this:
public int GetNextId<T>( DataContext db )
{
using ( var transaction = new TransactionScope ( TransactionScopeOption.RequiresNew ) )
{
var nextId = (from n in db.GetTable<NextId> ()
where n.TableName == typeof(T).Name
select n).Single ();
nextId.Value += 1;
db.SubmitChanges ();
transaction.Complete ();
return nextId.Value - 1;
}
}
Since all operations between creation of the data context and the call to SubmitChanges are part of one transaction, do I need to create a separate data context for retrieving next IDs? Each time I need an ID, I need to query and update a table inside a transaction to prevent multiple apps from grabbing the same value. The call to SubmitChanges() in the GetNextId() method would submit all previous operations, which I don't want to do.
Is a separate data context the only way, or is there something better I could try?

How can i get primary key value when i insert a new record?

I am using LINQ-to-SQL class. It has a method object.InsertOnSubmit() .But it returns void so can i get primary key values after inserting a record.
I want the primary key value of recently inserted record.
yes (Assuming it is an identity field).
Calling InsertOnSubmit alone doesn't send the insert to the db. You need to call SubmitChanges in order for any changes in the current datacontext instance to be sent to the db.
After you have called SubmitChanges, you can access the values from the instance you used when calling InsertOnSubmit. Linq to sql will populate those values for you when doing the insert (which occurs during SubmitChanges)
Check this example: http://msdn.microsoft.com/en-us/vbasic/bb737920.aspx#dynid
In short, you don't need to. The object itself is updated.
public void Add(Person person)
{
using (MyEntities context = new MyEntities())
{
Context.Persons.InsertOnSaveChanges(person);
Context.SaveChanges();
}
}
public void Foo()
{
Person p = new Person { name = "John", age = 20 }
Add(p);
Int32 id = p.id; // id contains the newly inserted object's id
}
Here's an example of how that works:
var dc = new MyDataContext();
var cust = new Customer{FirstName="John", LastName="Smith"};
dc.Customer.InsertOnSubmit(cust);
dc.SubmitChanges();
//after SubmitChanges(), the Id is filled from the database
var customerPrimaryKey = cust.Id;
If the model is set up properly, the PK should be set on the affected object (the one you just inserted) automagically.
HTH.
Seth
Once you have called the InserOnSubmit(),primary key value is set to the corrosponding fiels in youe table object. You can simply access that property to get Primary Key.
Are you calling SubmitChanges() on your data context after inserting the record? The changeset won't be evaluated until you do.