I'm using codeigniter 2.1.4 & datamapper orm. I know how to save relations to an object and I know how to delete them.
In this case I have a many-to-many relation, which I want to update with new values from a form. Now I can use this to save them which works just fine:
$ousergroupright = new Usergroupright;
$usergrouprights = $ousergroupright->where_in('id', $this->input->post('usergrouprights'))->get();
$ousergroup = new Usergroup;
$ousergroup->get_by_id($id);
$ousergroup->save($usergrouprights->all);
But this doesn't delete the records I "unchecked" in my form. I need to delete the objects I don't want related anymore. What would be the best way to do this (without using custom queries)?
A query like above with $ousergroup->where_not_in() before saving seems overkill to me (why query database and build objects just to delete a relation?):
$ousergroupright = new Usergroupright;
$usergrouprights = $ousergroupright->where_not_in('id', $this->input->post('usergrouprights'))->get();
$ousergroup = new Usergroup;
$ousergroup->get_by_id($id);
$ousergroup->delete($usergrouprights->all);
Any ideas?
There is a way to delete the objects you don't want related anymore without the need to query a database and build objects just to delete a relation. You can use the utility function query a run a custom SQL to delete all the unrelated objects WITHOUT needing to perform a database query, something like:
// Create usergroup object
$u = new Usergroup();
// your custom SQL query to delete the unrelated objects
$sql = "delete from usergrouprights where usergroup.id = ? and id usergrouprights.id not in (?)";
// Binding values
$binds = array($idUserGroup , $listOfSelectedItens);
// Run query to populate user object with the results
$u->query($sql);
More about DataMapper query utility function
http://datamapper.wanwizard.eu/pages/utility.html#query
Related
I have a settings table which i am trying to update. My table is empty and i need to insert some data into it.
I am using eloquent to insert
$s = new Settings;
$s->language = request('language');
$s->sitename = request('sitename');
$s->user_id = Auth::id();
$s->save();
return redirect('settings');
I have come across this function
$se = Settings::findOrNew($id); // if exist then update else insert
The findOrNew requires me to know the id before i can save.
How can insert or update without knowing the id(which may not even exist in the first place).
Well in that cause you can use firstOrNew
since you said your basis is you wanted to check if that user_id already exist in table then you use it as condition instead of id
first -> you use firstOrNew
this function do is
check if condition exist it then if it exist it will just return the first existing data
if not just insert a new data and return the new insert data
$s = User::firstOrNew(array('user_id' => Auth::id()));
Then -> after that you can now use that object and do what you wanted to do on it
$s->language = request('language');
$s->sitename = request('sitename');
$s->save();
I have run sqlmetal.exe agaisnt my database.
SqlMetal.exe /server:server /database:dbname /code:mapping.cs
I have included this into my solution. So I can now create an object for each of the database tables. Great. I now wish to use ling to query by database. Can I presume that none of the connection etc is handled by the output of sqlmetal.exe. If this is correct what ways can I use ling to query my database?
Does the generated code include a Data Context (a class which inherits from System.Data.Linq.DataContext)? If so, then that's probably what you're looking for. Something like this:
var db = new SomeDataContext();
// You can also specify a connection string manually in the above constructor if you want
var records = db.SomeTable.Where(st => st.id == someValue);
// and so on...
how can I build a table of "orders" containing "IdOrder", "Description" and "User"?... the "User" field is a reference to the table "Users", which has "IdUser" and "Name". I'm using repositories.
I have this repository:
Repository<Orders> ordersRepo = new OrderRepo<Orders>(unitOfWork.Session);
to return all Orders to View, I just do:
return View(ordersRepo.All());
But this will result in something like:
IdOrder:1 -- Description: SomeTest -- User: UserProxy123ih12i3123ih12i3uh123
-
When the expected result was:
IdOrder:1 -- Description: SomeTest -- User: Thiago.
PS: I don't know why it returns this "UserProxy123ih12i3123ih12i3uh123". In Db there is a valid value.
The View:
It is showed in a foreach (var item in Model).
#item.Description
#item.User //--> If it is #item.User.Name doesn't work.
What I have to do to put the Name on this list? May I have to do a query using LINQ - NHibernate?
Tks.
What type of ORM are you using? You mention "repositories" but does that mean LinqToSql, Entity Framework, NHibernate, or other?
It looks like you are getting an error because the User field is not loaded as part of the original query. This is likely done to reduce the size of the result set by excluding the related fields from the original query for Orders.
There are a couple of options to work around this:
Set up the repository (or context, depending on the ORM) to include the User property in the result set.
Explicitly load the User property before you access it. Note that this would be an additional round-trip to the database and should not be done in a loop.
In cases where you know that you need the User information it would make sense to ensure that this data in returned from the original query. If you are using LinqToSql take a look at the DataLoadOptions type. You can use this type to specify which relationships you want to retrieve with the query:
var options = new DataLoadOptions();
options.LoadWith<Orders>(o => o.User);
DataContext context = ...;
context.LoadOptions = options;
var query = from o in context.Orders
select o;
There should be similar methods to achive the same thing whatever ORM you are using.
In NHibernate you can do the following:
using (ISession session = SessionFactory.OpenSession())
{
var orders = session.Get<Order>(someId);
NHibernateUtil.Initialize(orders.User);
}
This will result in only two database trips (regardless of the number of orders returned). More information on this can be found here.
In asp.net MVC the foreign key doesn't work the way you are using it. I believe you have to set the user to a variable like this:
User user = #item.User;
Or you have to load the reference sometimes. I don't know why this is but in my experience if I put this line before doing something with a foreign key it works
#item.UserReference.load();
Maybe when you access item.User.Name the session is already closed so NHib cannot load appropriate user from the DB.
You can create some model and initialize it with proper values at the controller. Also you can disable lazy loading for Orders.User in your mapping.
But maybe it is an other problem. What do you have when accessing "#item.User.Name" from your View?
I am using Entity Framework for the first time and noticed that the entities object returns entity collections.
DBEntities db = new DBEntities();
db.Users; //Users is an ObjectSet<User>
User user = db.Users.Where(x => x.Username == "test").First(); //Is this getting executed in the SQL or in memory?
user.Posts; //Posts is an EntityCollection<Post>
Post post = user.Posts.Where(x => x.PostID == "123").First(); //Is this getting executed in the SQL or in memory?
Do both ObjectSet and EntityCollection implement IQueryable? I am hoping they do so that I know the queries are getting executed at the data source and not in memory.
EDIT: So apparently EntityCollection does not while ObjectSet does. Does that mean I would be better off using this code?
DBEntities db = new DBEntities();
User user = db.Users.Where(x => x.Username == "test").First(); //Is this getting executed in the SQL or in memory?
Post post = db.Posts.Where(x => (x.PostID == "123")&&(x.Username == user.Username)).First(); // Querying the object set instead of the entity collection.
Also, what is the difference between ObjectSet and EntityCollection? Shouldn't they be the same?
Thanks in advance!
EDIT: Sorry, I'm new to this. I'm trying to understand. Attached EntityCollections are lazy loaded, so if I access them then memory is populated with them. Rather than doing two querys to the object sets like in my last edit, I am curious if this query would be more what I was after:
DBEntities db = new DBEntities();
User user = (from x in db.Users
from y in x.Posts
where x.Username == "test"
where y.PostID == 123
select x).First();
ObjectSet<T> does implement IQueryable<T>, but EntityCollection<T> does not.
The difference is that ObjectSet<T> is meant to be used for querying directly (which is why it does implement the interface). EntityCollection<T>, on the other hand, is used for the "many" end of a result set, typically returned in a query done on an ObjectSet<T>. As such, it impelments IEnumerable<T>, but not IQueryable<T> (as it's already the populated results of a query).
I was almost ready to say yes, they both do. Luckily I check the documentation first.
EntityCollection does not implement IQueryable.
As for the difference, ObjectSet<TEntity> represents the the objects generated from a table in a database. EntityCollection<TEntity> represents a collection of entity objects on the 'Many' side of One to Many or Many to Many relationship.
I have created a linq query that returns my required data, I now have a new requirement and need to add an extra field into the returned results. My entity contains an ID field that I am trying to map against another table without to much luck.
This is what I have so far.
Dictionary<int, string> itemDescriptions = new Dictionary<int, string>();
foreach (var item in ItemDetails)
{
itemDescriptions.Add(item.ItemID, item.ItemDescription);
}
DB.TestDatabase db = new DB.TestDatabase(Common.GetOSConnectionString());
List<Transaction> transactionDetails = (from t db.Transactions
where t.CardID == CardID.ToString()
select new Transaction
{
ItemTypeID= t.ItemTypeID,
TransactionAmount = t.TransactionAmount,
ItemDescription = itemDescriptions.Select(r=>r.Key==itemTypeID).ToString()
}).ToList();
What I am trying to do is key the value from the dictonary where the key = itemTypeID
I am getting this error.
Local sequence cannot be used in LINQ to SQL implementations of query operators except the Contains operator.
What do I need to modify?
This is a duplicate of this question. The problem you're having is because you're trying to match an in-memory collection (itemDescriptions) with a DB table. Because of the way LINQ2SQL works it's trying to do this in the DB which is not possible.
There are essentially three options (unless I'm missing something)
1) refactor your query so you pass a simple primitive object to the query that can be passed accross to the DB (only good if itemDescriptions is a small set)
2) In your query use:
from t db.Transactions.ToList()
...
3) Get back the objects you need as you're doing, then populate ItemDescription in a second step.
Bear in mind that the second option will force LINQ to evaluate the query and return all transactions to your code that will then be operated on in memory. If the transaction table is large this will not be quick!