NHibernate LazyLoading - nhibernate

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.

Related

Syncfusion calender OnMonthCellLoaded custom event is passing a null to my command

Preface: Syncfusion provides a free Calender control called SfCalendar for Xamarin.Forms. This calender has an event called OnMonthCellLoaded. The problem with this event is that its eventargs is type MonthCell which does not inherit from System.EventArgs unfortunately. This is a problem because the eventargs of an event must inherit from System.EvenArgs in order for it to properly used by the Prism EventToCommand behavior.
Objective: I am trying to bind the OnMonthCellLoaded event using prism behaviors in order to set the data context of the MonthCell. I hope this is clear.
Current situation:
I have extended the SfCalendar calender like follow:
public class sfCalendarExtended : Syncfusion.SfCalendar.XForms.SfCalendar
{
public event EventHandler<MonthCellEventArgs> OnMonthCellLoadedExtended;
public sfCalendarExtended()
{
this.OnMonthCellLoaded += SfCalendarExtended_OnMonthCellLoaded;
}
private void SfCalendarExtended_OnMonthCellLoaded(object sender, MonthCell e)
{
if (this.OnMonthCellLoadedExtended != null)
{
if (e != null)
{
Debug.Print(e.Date.ToLongDateString());
var eventArgs = new MonthCellEventArgs() { Value = new MonthCell(e.Date) };
this.OnMonthCellLoadedExtended(this, eventArgs);
}
}
}
}
public class MonthCellEventArgs : System.EventArgs
{
public MonthCell Value { get; set; }
public MonthCellEventArgs()
{
}
}
This is my Xaml
<Controls:sfCalendarExtended x:Name="calendar">
<Syncfusion:SfCalendar.MonthViewSettings>
<Syncfusion:MonthViewSettings DateSelectionColor="#dddddd" CellTemplate="{StaticResource weathertemplate}"/>
</Syncfusion:SfCalendar.MonthViewSettings>
<Syncfusion:SfCalendar.Behaviors>
<prismbehaviors:EventToCommandBehavior EventName="OnMonthCellLoadedExtended" Command="{Binding BindMonthCellToDateCommand}"/>
</Syncfusion:SfCalendar.Behaviors>
</Controls:sfCalendarExtended>
Where controls is the alias for the namespace where the sfCalenderExtended class resides.
Now let's take a look at the Command implementation in my view model:
public DelegateCommand<MonthCellEventArgs> BindMonthCellToDateCommand { get; set; }
public ViewModel()
{
BindMonthCellToDateCommand = new DelegateCommand<MonthCellEventArgs>(
(MonthCellEventArgs obj) =>
{
// more code here
Now everything goes according to plan until I hit MonthCellEventArgs obj with the debugger and obj is always null.
Any help would be highly appreciated.
Alright, so I have emailed Syncfusion about this and they have addressed this issue by changing the args parameter of MonthCellLoaded event handler to inherit from System.EventArgs. More information in their online forum here.
My solution above works if and only if I use Corcav behaviors (see link) instead of Prism behaviors.
We have fixed the issue’s with “System.ArgumentException has been thrown while using EventToCommand behavior in SfCalendar”. As per the implementation Monthcell is moved to EventArgs from View and it is deprecated in OnMonthCellLoaded event and use MonthCellLoadedEventArgs. Please find the Custom assemblies for this fix below.
Custom assemblies: http://www.syncfusion.com/downloads/support/directtrac/217023/ze/Assembly1814496033.zip
Please clear the NuGet cache before replacing the custom assemblies. Please find the link below,
https://www.syncfusion.com/kb/6987/how-to-clear-nuget-cache
Assembly Version: 16.3.0.21
Installation Directions:
Replace the files “Syncfusion.SfCalendar.XForms.dll, Syncfusion.SfCalendar.XForms.Android.dll, Syncfusion.SfCalendar.XForms.iOS.dll” under following folders. Before replacing the new assemblies please take backup of old assemblies.
{Syncfusion Installed location} \Essential Studio\16.3.0.21\Xamarin\lib\pcl\Syncfusion.SfCalendar.XForms.dll
{Syncfusion Installed location} \Essential Studio\16.3.0.21\Xamarin\lib\Android\Syncfusion.SfCalendar.XForms.dll
{Syncfusion Installed location}\EssentialStudio\16.3.0.21\Xamarin\lib\Android\Syncfusion.SfCalendar.XForms.Android.dll
{Syncfusion Installed location} \Essential Studio\16.3.0.21\Xamarin\lib\iOS\Syncfusion.SfCalendar.XForms.dll
{Syncfusion Installed location}\EssentialStudio\16.3.0.21\Xamarin\lib\iOS\Syncfusion.SfCalendar.XForms.iOS.dll
Regards,
Vigneshkumar R

Nhibernate bind to DataGridView, insert doesn't work

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
}
}

SharePoint 2010 Rename Document on Upload Fails in Explorer View

I'm trying to implement a customization in SharePoint 2010 so that when a document is uploaded to a library, the file name is changed to include the Document ID in the name. (I know that people shouldn't worry about file names as much any more, but we have a lot of legacy files already named and users who like to have local copies).
I was able to implement a custom Event Receiver on the ItemAdded event that renames the file by adding the Document ID before the file name. This works correctly from the web Upload.
The problem is with the Explorer View. When I try to add the file using WebDAV in the Explorer View, I get two copies of the file. It seems that when a file is uploaded via the Web the events that fire are
ItemAdding
ItemAdded
But when I copy/paste a file into Explorer View I see the following events:
ItemAdding
ItemAdded
ItemAdding
ItemAdded
ItemUpdating
ItemUpdated
The result is I have two files with different names (since the Document IDs are different).
I've found a lot of people talking about this issue online (this is the best article I found). Anyone have any other ideas? Would it make more sense to do this in a workflow instead of an event receiver? I could use a scheduled job instead, but that might be confusing to the user if the document name changed a few minutes later.
This is my code that works great when using the Web upload but not when using Explorer View:
public override void ItemAdded(SPItemEventProperties properties)
{
try
{
SPListItem currentItem = properties.ListItem;
if (currentItem["_dlc_DocId"] != null)
{
string docId = currentItem["_dlc_DocId"].ToString();
if (!currentItem["BaseName"].ToString().StartsWith(docId))
{
EventFiringEnabled = false;
currentItem["BaseName"] = docId + currentItem["BaseName"];
currentItem.SystemUpdate();
EventFiringEnabled = true;
}
}
}
catch (Exception ex)
{
//Probably should log an error here
}
base.ItemAdded(properties);
}
I have found that using a Visual Studio workflow allows me the most flexibility to do this. A SharePoint Designer Workflow would be simpler, but would be harder to deploy to different sites and libraries.
After reading some good articles including this and this I have come up with this code which seems to work. It starts a workflow and waits until the document is not in a LockState and then processes the filename.
The workflow looks like this:
And here is the code behind:
namespace ControlledDocuments.RenameWorkflow
{
public sealed partial class RenameWorkflow : SequentialWorkflowActivity
{
public RenameWorkflow()
{
InitializeComponent();
}
public Guid workflowId = default(System.Guid);
public SPWorkflowActivationProperties workflowProperties = new SPWorkflowActivationProperties();
Boolean continueWaiting = true;
private void onWorkflowActivated1_Invoked(object sender, ExternalDataEventArgs e)
{
CheckFileStatus();
}
private void whileActivity(object sender, ConditionalEventArgs e)
{
e.Result = continueWaiting;
}
private void onWorkflowItemChanged(object sender, ExternalDataEventArgs e)
{
CheckFileStatus();
}
private void CheckFileStatus()
{
if (workflowProperties.Item.File.LockType == SPFile.SPLockType.None)
{
continueWaiting = false;
}
}
private void renameFile(object sender, EventArgs e)
{
try
{
SPListItem currentItem = workflowProperties.Item;
if (currentItem["_dlc_DocId"] != null)
{
string docId = currentItem["_dlc_DocId"].ToString();
if (!currentItem["BaseName"].ToString().StartsWith(docId))
{
currentItem["BaseName"] = docId + currentItem["BaseName"];
currentItem.SystemUpdate();
}
}
}
catch (Exception ex)
{
//Should do something useful here
}
}
}
}
Hope this helps someone else if they have the same problem.
Well i'd go for the workflow workaround... there are 2 options imo:
1) Create a boolean fied in your document library, then create a SPD workflow that fires when the item is added and set that field to "Changed" or something. In the EventReceiver you then check whether that field has been set..
2) Do everything with the SPD workflow - changing the title like in this example should be no problem.

Refreshing an entity throws an NHibernate.UnresolvableObjectException

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.

selecting items from a NetTiers EntityGridView

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
}