Can I update 1 object only with Linq to SQL? - linq-to-sql

Its a simple question, but I'm not aware of the answer and I couldn't get it to work.
Can I update only one entity on the entire DataContext? Or should I follow plain ADO.NET for this operation only?
Edit:
public MyObject GetMyObjectById(int selectedId)
{
DataContext db = _dbManager.GetContext();
return db.MyObject.SingleOrDefault(p => p.Id == selectedId);
}
I am getting an object with the above query...
I am querying then for an integer...on another table/object
public int GetMyInteger()
{
DataContext db = _dbManager.GetContext();
return db.MyAnotherObject.FirstOrDefault().MyInteger;
}
Everything is fine for all my operations...but now i just want to update only the integer i got from the database...
public void SetMyInteger(int updInteger)
{
DataContext db = new DataContext(ConnectionString);
MyAnotherObject theEntity = db.MyAnotherObject.FirstOrDefault();
atheEntity.MyInteger = updInteger;
db.SubmitChanges(ConflictMode.ContinueOnConflict);
}
The above method deleted MyObject i got from the first query!!! Of course if i use the static context DataContext tries to update MyObject and MyAnotherObject which seems the correct behaviour.
Edit:
I have changed the method getting the integer with a new datacontext as well and seems to working correctly, i have a strange thought on why called the delete method, because it was the method that was called, but again .. is working now...
Thank you all for your time.

Yes it's possible. What have you tried? It should be as simple as this:
using (var dc = new YourDataContext())
{
Person p = dc.Persons.Take(1).Single();
p.FirstName = "Ahmad";
dc.SubmitChanges();
}

Yes, you can:
Foo foo = dc.Foos.Where(foo => foo.Id == 345).Single();
foo.Name = "foo";
dc.SubmitChanges();

Related

Hibernate : add child to parent collection

I'm using Hibernate on a web project, which a have two different classes (Node, Interface)
Node
#Entity
#Table(name="NODES")
public class Node {
//...
#OneToMany(mappedBy="node", cascade={CascadeType.ALL, CascadeType.MERGE, CascadeType.PERSIST}, orphanRemoval=true)
private Set<Interface> interfaces = new HashSet<>();
//...
}
Interface
#Entity
#Table(name="INTERFACES")
public class Interface {
//...
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="REF_NODE")
private Node node;
//...
}
Everything is fine,
My question is how can I add an Interface(chlid) to a Node(Parent) that already persisted? means if i already has some Node in the database with 2 Interfaces for exemple and I want to add the third one, how i can do it?
My first quick solution is to use native sql in Hibernate, like this:
public void addInteface(Interface i, Long idNode) {
//OpenSession..
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction tx = null;
try {
//Start transaction
tx = session.beginTransaction();
//Native SQL in Hibernate
SQLQuery query = session.createSQLQuery("INSERT INTO INTERFACES (ID_INTERFACE, ALIAS, ID_NODE) VALUES (NULL, :Alias, :idNode)");
query.setParameter("ifAlias", i.getAlias());
query.setParameter("refNode", idNode);
//Some other parameters...
//Execute and Commit
query.executeUpdate();
tx.commit();
} catch (Exception e) {
if (tx != null) tx.rollback();
throw e;
} finally {
session.close();
}
}
It works, but it's not the best solution i believe.
NB: I found some topics here in stackoverflow with the almost same title but didn't answer my question.
It can be done in 2 ways.
1st Option:
node.getInterfaces().add(new Interface(....)); // you have orphan removal to true, this will work
session.saveOrUpdate(node);
tx.commit();
session.close();
Or
2nd OPtion
newInterface.setNode(nodeObject);
session.saveOrUpdate(newInterface);
tx.commit();
session.close();
In the above 2 methods, 2nd option works great compared to the first one. 1st one will pull all the children when you call getInterfaces(), which does not perform better.
//Syntax may not be on point, also some psuedcode
Lets say you want to add an interface to Node with an id that is 1:
Query query = session.createQuery("Select n from Node n where n.id = '1'");//JPQL
Node n = query.getSingleResult();
Then you will make a new Interface
Interface i = new Interface();
Then set the variables to what you want but also set the node
i.setVariables(..);
i.setNode(n);
Then update
session.merge(i);
Now all this is assuming generator id is correct and such.

Using Find in CodeFirst (EntityFramework) to get non-primary keys

My understanding is that find only takes the primary key as the parameter. That works great if the value you are looking for is actually the primary key. In my case, I have a class like this:
public class Chamber
{
[Key]
public int Id {get;set;}
public string ChamberName { get; set; }
}
I want to check whether a given ChamberName exists in either my context or the database itself. How can I do that? Do I have to somehow enumerate of the context myself first, then, look it up in the database with a call like db.Chambers.where(a=>a.ChamberName.equals...?
I can see it working well if ChamberName is my primary key, but it is not.
THanks,
There is a property called Local in the DbSet. You can query that first to find entities loaded to the context.
var entity = db.Chambers.Local.Where(/**/).SingleOrDefault();
if (entity == null)
{
entity = db.Chambers.Where(/**/).SingleOrDefault();
}
You can't use the .Find() method - but how about:
public Chamber FindByChamberName(string chamberName)
{
using(MyDbContext ctx = new MyDbContext())
{
Chamber result = ctx.Chambers
.FirstOrDefault(c => string.Compare(c.ChamberName, chamberName, true));
return result;
}
}
You don't have to manually enumerate anything - just retrieve the first occurence of a chamber by that name - or none.
If you just need to know whether a given chamber (specified by its ChamberName) exists or not, you could use the .Any() method in Linq:
using(MyDbContext ctx = new MyDbContext())
{
return ctx.Chambers.Any(c => string.Compare(c.ChamberName, chamberName, true));
}

LINQ To SQL does not work when adding new object

I use the following code to insert a new record to my Users table:
public bool CreateUser(User obj)
{
obj.Id = Guid.NewGuid();
using (_db = new CMSDataContext())
{
obj.SiteId = SiteID;
_db.Users.InsertOnSubmit(obj);
_db.SubmitChanges();
}
return true;
}
I do not get any errors, and everything seems fine. I can read a record from database with same DataContext. But after the above method runs completely, I see nothing new in my Users table. Why?
Is the id column truly a PK in the sql server database?

LinqToSql - "insert on submit"

I'm trying to insert a row in to one of my tables,
so I look over the web to find an example for using the DATACONTEXT and found this one:
protected void buttonSave_Click(object sender, EventArgs e)
{
using (NorthwindDataContext context = new NorthwindDataContext())
{
Customer customer = new Customer
{
CustomerID = textBoxCustomerID.Text,
CompanyName = textBoxCompanyName.Text,
ContactName = textBoxCustomerName.Text,
ContactTitle = textBoxTitle.Text,
Address = textBoxAddress.Text,
City = textBoxCity.Text,
Region = textBoxRegion.Text,
PostalCode = textBoxPostalCode.Text,
Country = textBoxCountry.Text,
Phone = textBoxPhone.Text,
Fax = textBoxFax.Text
};
context.Customers.InsertOnSubmit(customer);
context.SubmitChanges();
}
}
but when I try to use it and write : context.Guides. - now I can't see the InsertOnSubmit method..
does some one know why?
thanks,
yoni.
If you are using a LINQ-to-SQL Classes model (*.dbml), the Guides table must appear in the designer. Otherwise, the Guides class must descend from System.Data.Linq.Mapping.MetaTable.
Guides must be an object that doesn't implement the InsertOnSubmit method.

LINQ 2 SQL Query ObjectDisposed Exception

This one i had today is a strange one.
I have this query in an assembly method.
public Order[] SelectAllOrders()
{
Order[] orders;
using (MyDataContext context = new MyDataContext())
{
DataLoadOptions dlo = new DataLoadOptions();
dlo.LoadWith<Order>(order => order.OrderDetails);
context.LoadOptions = dlo;
orders = context.Orders.Select(p => p).ToArray();
}
return orders;
}
Supposed i already called the ToArray() the SQL Command executed and gave me the objects i need and i give them to a new Order[] array this should not need the DataContext instance.
While im serializing the Order[] i get from the method return, serializer tries to access the DataContext again and i get an exception that cannot access disposed object.
Tried without the using() statement and works like it should. But, why i get this behavior?
Anyone could give an explanation why deferred loading still remains while I'm calling .ToArray() and assigning new variable with the contents?
The Select(p=>p) achieves very little; you might as well just call:
orders = context.Orders.ToArray();
Re the problem - I would guess that either OrderDetails hasn't really loaded, or it is trying to load some other data lazily. I would suggest investigating by (in a dev session):
Order[] orders;
using (MyDataContext context = new MyDataContext())
{
context.Log = Console.Out; // show me
DataLoadOptions dlo = new DataLoadOptions();
dlo.LoadWith<Order>(order => order.OrderDetails);
context.LoadOptions = dlo;
Console.WriteLine("> Calling ToArray");
orders = context.Orders.ToArray();
Console.WriteLine("> ToArray complete");
// TODO: your extra code that causes serialziation, probably
// involving `DataContractSerializer`
Console.WriteLine("> Calling Dispose");
}
With this, you should be able to see any extra database trips that are happning after the ToArray but before the Dispose(). The point being: this data is needed for serialization, so either a: ensure it gets loaded, or b: exclude it from serialization.