I have a simple entity class in a WPF application that essentially looks like this:
public class Customer : MyBaseEntityClass
{
private IList<Order> _Orders;
public virtual IList<Order> Orders
{
get { return this._Orders; }
set {this._Orders = new ObservableCollection<Order>(value);}
}
}
I'm also using the Fluent automapper in an offline utility to create an NHibernate config file which is then loaded at runtime. This all works fine but there's an obvious performance hit due to the fact that I'm not passing the original collection back to NHibernate, so I'm trying to add a convention to get NHibernate to create the collection for me:
public class ObservableListConvention : ICollectionConvention
{
public void Apply(ICollectionInstance instance)
{
Type collectionType =
typeof(uNhAddIns.WPF.Collections.Types.ObservableListType<>)
.MakeGenericType(instance.ChildType);
instance.CollectionType(collectionType);
}
}
As you can see I'm using one of the uNhAddIns collections which I understand is supposed to provide support for both the convention and INotification changes, but for some reason doing this seems to break lazy-loading. If I load a custom record like this...
var result = this.Session.Get<Customer>(id);
...then the Orders field does get assigned an instance of type PersistentObservableGenericList but its EntityId and EntityName fields are null, and attempting to expand the orders results in the dreaded "illegal access to loading collection" message.
Can anyone tell me what I'm doing wrong and/or what I need to do to get this to work? Am I correct is assuming that the original proxy object (which normally contains the Customer ID needed to lazy-load the Orders member) is being replaced by the uNhAddIns collection item which isn't tracking the correct object?
UPDATE: I have created a test project demonstrating this issue, it doesn't reference the uNhAddins project directly but the collection classes have been added manually. It should be pretty straightforward how it works but basically it creates a database from the domain, adds a record with a child list and then tries to load it back into another session using the collection class as the implementation for the child list. An assert is thrown due to lazy-loading failing.
I FINALLY figured out the answer to this myself...the problem was due to my use of ObservableListType. In NHibernate semantics a list is an ordered collection of entities, if you want to use something for IList then you want an unordered collection i.e. a Bag.
The Eureka moment for me came after reading the answer to another StackOverflow question about this topic.
Related
I've been working with cakephp for personal use. Now I understood that I want to create some functions that will be repeated in many models of my project, so I found out by Cakephp docs that the best way to do it is using Behaviors.
Objective:
Each time a new entity of my project models are created, I want to notice some users(coworkers) by email. Like a new project added, new task added, etc...
What achieved until now
I created a behavior with an afeterSave event listener; I attached it in one of my models.
When I create I add a new task it runs the behaviors methods and send a simple email.
Problem
The problem is to find out witch model has called the event
I read the cake2.x docs and the afterSave event used to receive the event and the model in witch you could call alias to know the model name:
public function afterSave(Model $model,...){
$model_name = $model->alias;
if ($model_name == 'some_model'){
//code for specific model
} else (...)
}
However in cakephp 3.9 we receive Event and EntityInterface:
public function afterSave(Event $event, EntityInterface $model)
{
# I tried $mail_HTMLmessage= $model->_registryAlias;
# I tried $mail_HTMLmessage= $model->_className;
# I tried $mail_HTMLmessage= $model->get('className');
$this->sendMail($mail_HTMLmessage);// this is another method that i defined in my behavior that sends an email to me with the string mail_HTMLmessage as the mail message.
return true;
}
I've tested mail_HTMLmessage=$event->getName() and in my email I received event.afterSave as expected.
However everything I tried to get model/class name it returned an empty string.
Is it possible to get the model name? and what is the best way to do it?
Thanks in advance
I believe what you're looking for is not in the event at all, but the entity. getSource(), to be specific.
I might be not getting how some stuff work in Blazor, but here's what my issue is:
whenever I want to edit an object for example People object, I select it in #page "/people" from a table, then I'm redirected to the #page "people/edit/id". In #page "people/edit" I have an EditForm with InputText corresponding to the people model and the #bind value, everything is normal, it loads the data correctly.
The problem is when I edit some of the inputs and not save the data, just modify its values, and then go back to the #page "people", or anywhere, the object is modified.
I even put a breakpoint to watch the object being pulled from the database through Entity Framework Core, and it shows the modified version too, but checking on the database table, it does not seem to be affected.
It sounds impossible, but I tried with brand new projects, or others people projects in video tutorials, try replicating and does the same thing, so what's the deal here?
#page "/People/edit{id}"
#code {
[Parameter] public string id { get; set; }
Person person = new Person();
protected override async Task OnParametersSetAsync()
{
person = await PersonService.GetByIdAsync(id);
}
}
Firstly, if you put some object as a model for an EditForm and make some changes to it, all changes are reflected in the object immediately, but not after you click a submit.
Secondly, when you pull an object from a database it gets attached to the DbContext and stays attached, unless you detach it explicitly. When you query the entity, already attached to the context, the context does not query the database again, but gives you the attached entity. And if you have made some changes to it, you get these changes.
But those changes are not saved to database until you execute context.SaveChanges, so when you see the actual database, you see the unchanged data.
The difference with Net Core MVC is that Net Core MVC is stateless. Though you use references to the .NET objects in .cshtml files, they are used only during one query and get destroyed after the response is sent to client. When you use Blazor, you get actual .NET runtime ether on server (Blazor server) or on client (Blazor wasm), so your objects remain and preserve their state.
My model consisted of the following example:
class Aggregate {
private SomeClassWithFields property;
}
Now I decided to introduce inheritance to SomeClassWithFields. This results in:
class Aggregate {
private AbstractBaseClass property;
}
The collection already contains a lot of documents. These documents do not contain a _class property inside the DB since they were stored before the inheritance was present.
Is there a way to tell Spring Data MongoDB to use SomeClassWithFields as the default implementation of AbstractBaseClass if no _class property is present?
The other solution would be to add the _class to all the existing documents with a script but this would take some time since we have a lot of documents.
I solved it by using an AbstractMongoEventListener
The AbstractMongoEventListener has an onAfterLoad method which I used to set the default _class value if none was present :) This method is called before any mapping from the DBObject to my domain model by spring so it works then.
Do note that I also needed to let spring data mongodb know the mappingBasePackage in order for it to be able to read an Aggregate before writing one. This can be done implementing the getMappingBasePackage method of the PreconfiguredAbstractMongoConfiguration class.
In my Fusion Web Application, I have defined several business rules in entity objects. Everything works fine. The problem is that I can not get them programatically. I have searched through the EntityObjects Impl java class, but there is no method that should perform validation. Does anyone know any way, how to get the business rules from an entity object? I need to get at least a list of those.
Update:
EntityDefImpl eoDef = EntityDefImpl.findDefObject("package...MyEO");
for (Object o : eoDef.getValidators()) {
System.out.println("Rule: " + o);
}
But even in this case, I do not get a list of business rules.
Try the following instead of your implementation
EntityDefImpl eoDef = EntityDefImpl.findDefObject("package...MyEO");
AttributeDefImpl myAttribute=getAttributeDefImpl("MyAttribute"); //Get the first Attribute
for (Object o : myAttribute.getValidators()) {
System.out.println("Rule: " + o);
}
The one you did will get the Entity level validators only, this one will get you this specific attribute validators!
Take a look at the EntityDefImpl class. Since it applies to all EO instances it carries the validation.enter link description here
If you just want to call it, you can use the Validate function from ViewObjectImpl (Since you want to call it from the Web Application programmatically or your Application Module)
If you want to add another Validation, then you should follow the first answer.
the title pretty much explains my issue:
I am right now taking care of drag & drop in my app. I can have many instances of my app running at the same time, and I can drag from one instance to the other without trouble.
Now, I would like to know if I'm drag & dropping "internally" (i.e: the drop occurs in the same instance as the drag) or "externally" (the opposite)
I went this far: I need to add to my dragged data a unique ID (something like a PUID) that identifies the app where I'm making the drag. Then I can just compare this id to the one I have locally on the drop and see if it is the same.
I have no problem transferring such info in my drag Data, the issue is more to find this UId.
I have been thinking using the Process.GetCurrentProcess().MainWindowHandle; but I'm not sure if this is a good idea.
What option(s) do I have to make this work?
I would simply create a readonly Guid that gets set when you start your app.
You can put this wherever your main logic lives (MainWindow or ViewModel).
Here is a snippet:
public class MyViewModel
{
private readonly Guid mUID = Guid.NewGuid();
// In case you want a property for it
public string UniqueApplicationID
{
get { return mUID; }
}
public void OnDropHandler(MyViewModel objectBeingDropped)
{
if (objectBeingDropped.UniqueApplicationID == mUID)
return;
// Handle drop normally here
}
}
The D-n-D is much like an UI activity, than an internal one.
I would distinguish two contexts: dropping a file, and dropping some object (e.g. VS designer). In the first context there's no problem at all, because it doesn't matter where you pull the data. In the second case, you should know what object has been chosen. For instance, you have a listbox with many items (e.g. the alphabet chars), once the user D-n-D any of those items, the internal operation is a simple reference to the selected object. By pulling the data from another app, you won't be able to find your object, because the source is different.
In case of structs or strings, you may wrap them with a GUID, as you correctly proposed.