Im in a bit of a jam.
Problem
NHibernate forces me to make a foreignkey column nullable, which is a very bad idea for our database and quite ugly.
Is there a work around for this?
Situation
I have the following maps (names changed for simplicity):
public class BillMap : SequenceGeneratedIdEntityMap<Bill>
{
public BillMap()
{
Id(x => x.Id).GeneratedBy.Native("BILL_SEQ");
... (maps) ...
HasMany<Expense>(f => f.Expense)
.Schema("ACCOUNT")
.Table("EXPENSE")
.KeyColumn("BILL")
.Cascade.All();
}
}
public class ExpenseMap : SequenceGeneratedIdEntityMap<Expense>
{
public ExpenseMap ()
{
Id(x => x.Id).GeneratedBy.Native("EXPENSE_SEQ");
... (maps) ...
}
}
Using these maps I get the following from NHibernate when saving an instance of Bill:
select ACCOUNT.BILL_SEQ.nextval from dual
select ACCOUNT.EXPENSE_SEQ.nextval from dual
command 0:INSERT INTO ACCOUNT.BILL(...)
command 0:INSERT INTO ACCOUNT.EXPENSE(...)
command 0:UPDATE UPDATE.EXPENSE SET BILL = X WHERE ...
Notice 2 things here:
All id's are requested from the sequences BEFORE the inserts.
The foreignkey is not updated until AFTER the expense has been inserted.
This forces me to make the column nullable AND to allow updates on the table.
Ideally the update statement should not be necessary and handled some deep dark place inside NHB :).
This could be solved by making a bidirectional reference, but that would destroy my model :/.
I do believe this a returning issue for me (never found a good solution before). Are there anyone who knows of workaround?
Kind regards
By setting .Inverse() on your HasMany<Expense> call, NHibernate will be aware of which side is the 'parent' object. I believe that will swap the order of the inserts.
For more information:
http://wiki.fluentnhibernate.org/Getting_started#Mappings
Inverse Attribute in NHibernate
Related
I have following table:
$table->boolean('prop_enabled');
$table->boolean('prop1_enabled')->nullable();
$table->boolean('prop2_enabled')->nullable();
$table->boolean('prop3_enabled')->nullable();
My requirement is when prop_enabled is false, then prop1_enabled, prop2_enabled and prop3_enabled values shall be set to null during row insertion or update.
Is my table design is appropriate for solving the problem?
If my table is good to solve the problem, which approach is better to handle my requirement? I have options to create trigger on database, or to override Create and save method from Model class.
I believe the best approach is doing the Observer solution. Using an mutator, requires a lot of mutators to secure your data structure and / or business logic that can ignore it. The observer is using events and there for you can only circumvent it from triggering by avoiding using eloquent.
You can hook into the saving event on Models. This will look at the model before saving it, then alter it, if your case is true and thereby creating the optimal 1 query insertion. No matter how your business logic is, this will trigger before the creation or updating.
class YourModelObserver {
public function saving(YourModel $model) {
if ($model->prop_enabled === false) {
$model->prop1_enabled = false;
$model->prop2_enabled = false;
$model->prop3_enabled = false;
}
}
}
In a provider you have to register your listener.
public function boot()
{
YourModel::observe(YourModelObserver::class);
}
My biggest problem with your design is a common code smell i have seen before. Naming variables after numbers, when you have multiple just seems wrong for me. What happens if you get the 4. prop and how will you handle showing them and updating em? An alternative approach would be to have em in a more generic fashion in another table when they had a name or key instead of being prop1 or prop2 and having logic associated with creating them or updating em. If you are certain the prop1, prop2 and prop3 are not gonna change the design is good for now.
I've been searching for an answer on how to delete ALL records from a table using LINQ method syntax but all answers do it based on an attribute.
I want to delete every single record from the databse.
The table looks like so:
public class Inventory
{
public int InventoryId { get; set; }
public string InventoryName { get; set; }
}
I'm not looking to delete records based on a specific name or id.
I want to delete ALL recods.
LINQ method syntax isn't a must, bt I do prefer it since it's easier to read.
To delete all data from DB table I recommend to use SQL:
Trancate Table <tableName>
Linq is not meant to change the source. There are no LINQ methods to delete or update any element from your input.
The only method to change you input, is to select the (identifiers of the )data that you want to delete in some collection, and then delete the items one by one in a foreach. It might be that your interface with the source collection already has a DeleteRange, in that case you don't have to do the foreach.
Alas you didn't mention what your table was: Is it a System.Data.DataTable? Or maybe an Entity Framework DbSet<...>? Any other commonly used class that represents a Table?
If you table class is a System.Data.DataTable, or implements ICollection, it should have a method Clear.
If your tabls is an entity framework DbSet<...>, then it depends on your Provider (the database management system that you use) whether you can use `Clear'. Usually you need to do the following:
using (var dbContext = new MyDbContext(...))
{
List<...> itemsToDelete = dbContext.MyTable.Where(...).ToList();
dbContext.MyTable.RemoveRange(itemsToDelete);
dbContext.SaveChanges();
}
Here is my issue.
I have a customer table and an address table. The customer table has two foreign keys to the address table. ShippingAddressFK and BillingAddressFK
Normally I'd just have AddressFK if it was just one foreign key. But since it's two I'm not sure how to go about it.
I saw this:
Fluent Nhibernate AutoMapping -- 2 foreign keys to same table?
But I'm not sure how to translate that to the Sharp Lite Architecture override .cs file.
In the MyStore example this was the closest I could find:
public class OrderOverride : IOverride
{
public void Override(ModelMapper mapper) {
mapper.Class<Order>(map => map.Property(x => x.OrderStatus,
status => {
status.Type<OrderStatusCustomType>();
status.Column("OrderStatusTypeFk");
}));
}
}
I notice they are similar I'm just not sure how to change the solution above to fit this sort of override class in the Sharp Lite Architecture
No access to visual studio so haven't tried this out, consider psuedo code based on the code you pasted and the code in the other question you linked to:
public class CustomerOverride : IOverride
{
public void Override(ModelMapper mapper) {
mapper.Class<Customer>(map => map.Property(x => x.BillingAddress,
address => {
address.Type<Address>();
address.Column("BillingAddressFk");
}));
mapper.Class<Customer>(map => map.Property(x => x.ShippingAddress,
address => {
address.Type<Address>();
address.Column("ShippingAddressFk");
}));
}
}
I just had a look at Order override in SharpLite and this isn't fluent nhibernate, it is nhibernate code mapping which I have never used. that might not be the correct way to define multiple property overrides but hopefully the code above will work. if not change the fluentnhibernate tag to nhibernate and some1 who knows more about it should be able to help.
The example you are referring to is for mapping one of your properties to a custom type, like an Enum.
You need to map your relationship to the multiple addresses, and give it a different column name than what your conventions would.
public void Override(ModelMapper mapper)
{
mapper.Class<Customer>(map =>
map.ManyToOne(
x => x.BillingAddress,
x => x.Column("BillingAddressFk")));
mapper.Class<Customer>(map =>
map.ManyToOne(
x => x.ShippingAddress,
x => x.Column("ShippingAddressFk")));
}
Notice the ManyToOne instead of Property.
I'm using Subsonic 3 and Automapper on an asp.net MVC3 project.
In my HttpPost ActionResult, I'm taking my model and mapping it to my Subsonic generated entity.
The mapping works no probs, but I can't update the entity.
Upon further inspection, it is because I have no dirty columns, therefore my call to Update() fails as Subsonic doesn't think it needs to update anything.
I've re-jigged the code loads - even forcing the method to load the entity from the db again before mapping against the model. It just seems that the mapping destroys the dirtyColumns tracking. E.g. if I map after loading from the DB, and then change a random property, it doesn't get marked as a dirty column.
I've also tried using the SetIsLoaded(true) method call. No joy after mapping.
Here's my method:
[HttpPost]
public virtual ActionResult Edit(SinglePersonModel model)
{
if (ModelState.IsValid)
{
Data.Person person;
//Now Map my model to my entity - this works
Mapper.CreateMap<SinglePersonModel, Data.Person>();
person = Mapper.Map<SinglePersonModel, Data.Person>(model);
//THIS DOESN'T SET MY COLUMN TO DIRTY
person.Link = "asdjsadij";
//THIS DOESN'T SET MY COLUMN TO DIRTY EITHER
person.SetIsLoaded(true);
person.Link = "asdjsadij";
if (person.PersonId > 0)
PersonRepository.UpdatePerson(person);
else
PersonRepository.CreatePerson(person);
return RedirectToAction(MVC.SecureAdministration.Person.Index());
}
else return View(model);
}
The Static methods on my PersonRepository just call subsonic's Update() and Save() respectively.
Any ideas would be much appreciated. I'm now thinking that I may need to put some additional properties into my model to make sure that they get carried over into the entity by the automapper.
In the worst case I'll have to just not use the Automapper when mapping back to entities from the model, which would suck.
AutoMapper.Mapper.Map<SinglePersonModel, Data.Person>(model, person); - Have you tried it like this? This doesn't assign a new instance of the object but assigns it to the existing object. Just a thought. I understand the want of not loading it from the db. But figured this might help a bit :)
Thanks for that - glad to help out :)
I've got a situation where I need to prefetch some entities through a many-to-many relationship. So it's like the classic BlogPost <- BlogPostTag -> Tag situation.
Yes, I'm aware of LoadOptions but I can't use it because it's a web application and I'm using the one datacontext per request pattern.
It also seems you can't use projection to prefetch many-to-many relationships. Yes? No?
I want to return IQueryable<Tag> based on a set of Blogs. The best I can do is get it to return IQueryable<IEnumerable<Tag>> by doing the following:
public IQueryable<Tag> GetJobsCategories(IQueryable<BlogPost> blogPosts)
{
var jobCats = from bp in blogPosts
select bp.BlogPostTags.Select(x => x.Tag);
return jobCats;
}
Can I flatten that? Am I missing something obvious? Is there another approach I can take?
And no, I can't change ORMs ;-)
This will work, you can just drill down in the linq query
public IQueryable<Tag> GetJobsCategories(IQueryable<BlogPost> blogPosts)
{
return from bp in blogPosts
from tag in bp.BlogPostTags
select tag;
}
If you declare the method as such:
public static IQueryable<Tag> GetJobsCategories(this IQueryable<BlogPost> blogPosts)
You can use it as extension method on queryables. For instance
myContext.BlogPosts.GetJobsCategories()