I am using a nettiers generated EntityGridView, and I've added a method for OnSelectedIndexChanged. In that method, How do I get the currently selected entity from the EntityGridView?
Ok.. I got it. It was stupidly simple. Maybe not the best way, but I fooled around until I got the following code that worked, using the SelectedDataKey from the GridView and the EntityProvider to retrieve the entity data.
public void GridView1_SelectedIndexChanged(Object sender, EventArgs e)
{
int idEntity = Int32.Parse( GridView1.SelectedDataKey.Value.ToString());
s.Entities.MMEntity ent =
s.Data.DataRepository.MMEntityProvider.Get(
new s.Entities.MMrKey(idEntity)
);
// use the entity here
}
Related
To bind an NHibernate class to a DataGridView I do:
IList<DatabaseAccess.poco.Employee> employees =
(from e in session.Linq<DatabaseAccess.poco.Employee>() select e).ToList<DatabaseAccess.poco.Employee>();
this.employeeBindingSource.DataSource = employees;
And when I commit, only changes on rows that already exist in the database are sent, using the grid to create a new row doesn't work.
So, can I expect that binding a list to DataSource is enough and I don't have to create Employee object and do session.Save(new_employee);? Or is it a must?
I haven't found any tutorial that describes a full DataGridView bind along with creating new rows.
It's a must. DataGridView has no knowledge about NH and NH has no knowledge that DataGridView added a new row. So you must, for example, in UserAddedRow event handler save new entity.
using (ITransaction tx = session.BeginTransaction())
{
session.Save(albumBindingSource.Current);
tx.Commit();
}
In page_load method, Is your datagrid bind in IsPostBack.
like this:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
//Grid Bind
}
}
For an ASP.Net project I'm using (Fluent) NHibernate for the persistence and JQGrid for displaying the data in a table. But when I want to use the AutoComplete feature of JQGrid I get an System.ArgumentException: Column 'HibernateLazyInitializer' does not belong with this table. while obtaining the data in an AJAX Request.
But this error occurs only sporadically and when some kind of proxyclass is used in the list. Therefore I think it has something to with the lazyloading of NHibernate.
protected new void Page_Load(object sender, EventArgs e)
{
base.Page_Load(sender, e);
_jqAutoComplete.DataSource = Session.CreateCriteria<Domain.Brand>()
.List<Domain.Brand>();
_jqAutoComplete.DataBind();
}
Usually the lazyloading is a pretty cool feature. Only in this case it leads to an error and therefore I don't want to disable it in the whole project. So, is there a way of modifying the CreateCriteria for not using LazyLoading but EagerLoading in this one case?
Or is there something else I'm missing?
If there is a good tutorial for understanding LazyLoading I would be glad too.
I solved the problem differently. Now I'm converting the Domain-Object into the corresponding object from the ViewModel. I'm using ValueInjecter for accomplishing the mapping.
protected new void Page_Load(object sender, EventArgs e)
{
base.Page_Load(sender, e);
var objList = service.getList<Domain.Brand>();
IList<V> list = new List<ViewModel.Brand>();
foreach (var el in objList)
{
var brand = new ViewModel.Brand();
list.Add(brand.InjectFrom<FlatLoopValueInjection>(el));
}
_jqAutoComplete.DataSource = list;
_jqAutoComplete.DataBind();
}
That solution works for me but I'm not totally happy with that.
The entities and mappings I'm talking about in this question can be found here :)
Here is the context:
I have a parent view-model which helps to manage some entities, and which has its own session.
From this VM, I open another view-model (with its own session too), do some changements to the entity (add and/or remove children), and when I validate the changements, I commit the session and warns the first view-model to refresh the display:
public void Validate()
{
using (var tx = Session.BeginTransaction())
{
try
{
SelectedTeam.ClearRoster();
foreach (var teamPlayer in TeamPlayers)
SelectedTeam.AddPlayer(teamPlayer);
teamsRepository.SaveOrUpdate(SelectedTeam);
tx.Commit();
}
catch (Exception ex)
{
tx.Rollback();
}
finally
{
if (tx.WasCommitted)
ServiceLocator.Current.GetInstance<Mediator>().NotifyColleagues(MediatorMessages.DisplayEntityInfos, SelectedTeam.Id);
}
}
}
Here is the faulted method of the parent VM:
public void RefreshEntitiesListAndDisplayEntityInfos(int selectedEntityId)
{
TEntity entity = entitiesRepository.Load(selectedEntityId);
Session.Refresh(entity);
//...
}
The exception is thrown at the Refresh line:
NHibernate.UnresolvableObjectException
And the message is:
No row with the given identifier exists[Emidee.CommonEntities.PlayerInTeam#3
I can open and change the entity multiple times, but it seems that the exception is thrown when I delete a children, then add another one, and finally delete another one.
After some readings on the web, it seems that's because when I refresh the entity, and because I changed the HasMany relationship (because I have deleted a player for example), NH tries to reload the deleted row.
I've tried to add a NotFound.Ignore statement on the HasMany in my mappings, I've tried to force a new query to the DB instead of a Load, but I still get this exception.
Does someone know how I could fix that?
Thanks in advance
Mike
This is a known behavior when refreshing objects with modified collections.
To force reload, change your method to do session.Evict with the entity as a parameter. This is the code we use in our base model class:
public T ReGet<T>(T entity) where T : IEntity
{
var id = entity.Id;
Session.Evict(entity);
return Session.Get<T>(id);
}
Well, I've just spotted the problem.
To update the players list of the team, I used to clear the list, and add the new players, before updating the entity.
Now, I update the list by removing and adding only the players who have been moved by the user, and I don't have any problems at all now.
That's weird. I don't know what was wrong before, but as least that works now.
How to get the sql generated by LinqToSql for update method?
I use the following code to show the sql generated by LinqToSql in VS2008's debug output window, but it only gets the sql select method generated,
how can I find the sql update method that was generated by LinqToSql?
I know the Sql Server Profiler and LinqPad can get it(the sql-update generated), but I want to show them in VS2008 or Log them to a file.
public partial class Linq2 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
DemoDataContext ctx = new DemoDataContext ();
// Then attach it to the Log property of your DataContext...
ctx.Log = new DebugTextWriter();
var product = ctx.Products.FirstOrDefault();
product.ProductName = "NewName1";
ctx.SubmitChanges();
}
}
// Add this class somewhere in your project...
public class DebugTextWriter : System.IO.TextWriter
{
public override void Write(char[] buffer, int index, int count)
{
System.Diagnostics.Debug.Write(new String(buffer, index, count));
}
public override void Write(string value)
{
System.Diagnostics.Debug.Write(value);
}
public override Encoding Encoding
{
get { return System.Text.Encoding.Default; }
}
}
And I get the sql-select query in the VS2008 debug output window:
SELECT TOP (1) [t0].[Id], [t0].[ProductName] ……
FROM [dbo].[Products] AS [t0]
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.30729.1
Your Database context object has a Log method that you can override. Your full Update statement, and every SQL command generated by Linq-To-SQL, can be captured via this Log method. I know this works because I use it to capture all our queries in our app. Just keep in mind that L2S can send a fair amount of output to the Log method, so make sure to capture it all. Your Update statement is in there somewhere.
Thank you for all answers.
I have found Linq To Sql Profiler to solve the problem.
Based on this link it looks like I can get date inserted / date modified information "for free" (without the need for triggers etc.) using Sql Server 2008 by simply enabling Change Tracking. I am using Entity Framework to access the data. My question is, how do I access date modified / date inserted information for the database records via Entity Framework and LINQ?
I'm using VS2008 so I don't have the new EF v4 stuff yet (but if it can be done in the new EF please let me know).
Thanks.
Aw, nevermind. I found it plenty easy to just create the Inserted and LastModified columns in each table myself, set a default value for each, and build an update trigger for LastModified. That seems to be what people do, and the Change Tracking looks like it's mainly set up for sync'ing. Right?
OK, this works beautifully (also see this article)...
public partial class MyEntities
{
partial void OnContextCreated()
{
this.SavingChanges += new System.EventHandler(CustomSavingChangesLogic);
}
/// <summary>
/// Apply timestamps
/// </summary>
public void CustomSavingChangesLogic(object sender, System.EventArgs e)
{
var changedEntities = ((ObjectContext)sender).ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Modified);
foreach (var stateEntryEntity in changedEntities)
{
if(!stateEntryEntity.IsRelationship) {
var entity = stateEntryEntity.Entity;
var lastModifiedPropInfo = entity.GetType().GetProperty("LastModified");
if (lastModifiedPropInfo != null)
lastModifiedPropInfo.SetValue(entity, DateTime.UtcNow, null);
if (stateEntryEntity.State == EntityState.Added)
{
var createdPropInfo = entity.GetType().GetProperty("Created");
if (createdPropInfo != null)
createdPropInfo.SetValue(entity, DateTime.UtcNow, null);
}
}
}
}
}