I have a MySQL table structure that looks like this:
Countries -> Countries_Regions (FK: country_id) -> Countries_Regions_Cities (FK: region_id)
So, there's a one-to-many relationship between country and region, and there's a one-to-many relationship between region and city
I tried to link them with the following classes:
class Model_Country extends ORM {
protected $_has_many = array('regions' => array("model" => "Countries_Region"));
}
class Model_Countries_Region extends ORM {
protected $_has_many = array('cities' => array("model" => "Countries_Regions_City"));
protected $_belongs_to = array('country' => array("model" => "Country"));
}
class Model_Countries_Regions_City extends ORM {
protected $_belongs_to = array('region' => array("model" => "Countries_Region"));
}
Everything goes fine if I try to find all the regions with
$country = ORM::factory("country", 1);
$region = $country->regions->find_all();
But when I try to find all the cities bottom-up, with
$country = ORM::factory("country", 1);
$city = $country->regions->cities->find_all();
It does recognize the city property in region, but it returns an empty row with all the city values set to NULL.
I feel like I'm missing something very obvious, but I can't figure out what it is. Please help me.
It does recognize the city property in region
Because $country->regions returns an ORM object with prepared WHERE statements, not a list of regions. If you call $country->regions->find_all(), you will get an array of regions, but after that you can access to their cities only through foreach loop.
There is a simple way, I think. Just add a country_id field to a City model and define a Belong_To relationship. So you will be able to use $country->cities or $city->country without loading regions.
Related
tables in my EntityFramework model are events, eventtypes, subevents, subeventtypes
using the MVC5 builders (right click on controllers, add, add controller) I created controllers and views for the last three tables without issue however when I create the controller and views for the events entity I produce the following errors
Keyword, identifier, or string expected after verbatim specifier: #
'EventType' is a type, which is not valid in the given context
the code that was generated in the event controller is
{
private Entities db = new Entities();
// GET: Events
public ActionResult Index()
{
var events = db.Events.Include(# => #.EventType); ERROR HERE
return View(events.ToList());
}
any help with this issue would be greatly appreciated
TIA
I experienced the same issue when using the "MVC Controller with views, using Entity Framework" template.
var #group = await _context.Groups
.Include(# => #.Company)
.FirstOrDefaultAsync(m => m.GroupId == id);
My workaround was simple to replace the # symbol with another character i.e. g
var #group = await _context.Groups
.Include(g => g.Company)
.FirstOrDefaultAsync(m => m.GroupId == id);
i have create an sql function in my database that take to Date params and get data from 5 tables.
after that add it to project as entity framework from database and the code generated is:
[DbFunction("Dr_EmploEntities", "SelectEmployee")]
public virtual IQueryable SelectEmployee(Nullable frm_date, Nullable to_date)
{
var frm_dateParameter = frm_date.HasValue ?
new ObjectParameter("frm_date", frm_date) :
new ObjectParameter("frm_date", typeof(DateTime));
var to_dateParameter = to_date.HasValue ?
new ObjectParameter("to_date", to_date) :
new ObjectParameter("to_date", typeof(DateTime));
return ((IObjectContextAdapter)this).ObjectContext.CreateQuery("[Dr_EmploEntities].[SelectEmployee](#frm_date, #to_date)", frm_dateParameter, to_dateParameter);
}
public DbSet SelectEmployee_Result { get; set; }
as you see i have now "SelectEmployee_Result" that don't take any params, and "SelectEmployee" that take two date params.
after that i have create an controller for "SelectEmployee_Result" class.
after that i run my project Index View that working with "SelectEmployee_Result" class give me err:
"The type 'SelectEmployee_Result' is mapped as a complex type. The Set method, DbSet objects, and DbEntityEntry objects can only be used with entity types, not complex types."
and i make breakpoint and see that "SelectEmployee_Result" has no data so i change the Index Code in controller and fill "SelectEmployee" with two date params
and when run got same err msg too.
so how can i fill "SelectEmployee_Result" from the beginning with data between two dates to let me use it in all views ?
all what i need here is view data i got i edit before saving it in database Like using DataTable but i need to do that from Entity with sql function
and what is difference between "SelectEmployee" that is my function name and that is need two params and "SelectEmployee_Result"?
I'm using a function to allow query composition from Web UI and I would to implement paging functionality which it will be available for dataBound controls such as ObjectDataSource, gridView, etc:
public class MyClass<TEntity> where TEntity : class
{
FakeEntities xxx = new FakeEntities();
public IEnumerable<TEntity> Get(Func<IQueryable<TEntity>, IQueryable<TEntity>> queryExpression)
{
var query = xxx.Set<TEntity>();
return queryExpression(query).ToList();
}
public int Count()
{
// What Can I return?
}
}
// **** USAGE ****
MyClass<User> u = new MyClass<User>();
var all = u.Get(p => p.Where(z => z.Account == "Smith").OrderBy(order => order.IdOther).Skip(1).Take(2));
The above query use Take and Skip function, so can I get real count of my entities? Obviously I must return Query Count without modifying filter expression.
I found this solution: Get count of an IQueryable<T>
However I get targetInvocationException with inner message {"This method supports the LINQ to Entities infrastructure and is not intended to be used directly from your code."}
I know my request could be freak-abnormal, because best practice should to impose to move "presentation needs" to some wrap class and that's is what I'll do. So I don't need anymore to get Count entities on my business logic class.
That's just UI concern only.
Thank you the same.
I have been struggling with what I thought would be simple.
I have a content type called Supplier. This supplier has contact information containing two addresses, one for Correspondence Address and one for Visiting Address. The supplier has also several locations, like location north and location south. A location is also an address. So basically I have a content item Supplier with a lot of addresses and all of them with their own type.
Migration:
public int Create() {
//Creating the Location contentrecord, contentpart and contenttype
SchemaBuilder.CreateTable("LocationPartRecord", table => table
.ContentPartRecord()
.Column<int>("LocationsPartRecord_id")
);
ContentDefinitionManager.AlterPartDefinition("LocationPart", part => part
.Attachable(false)
.WithField("LocationName", f => f.OfType("TextField"))
.WithField("AddressLine1", f => f.OfType("TextField"))
.WithField("AddressLine2", f => f.OfType("TextField"))
.WithField("Zipcode", f => f.OfType("TextField"))
.WithField("City", f => f.OfType("TextField"))
.WithField("Country", f => f.OfType("TextField")));
ContentDefinitionManager.AlterTypeDefinition("Location",
cfg => cfg
.WithPart("CommonPart")
.WithPart("LocationPart")
);
//Creating the Locations 'container' contentpart
SchemaBuilder.CreateTable("LocationsPartRecord", table => table
.ContentPartRecord()
);
ContentDefinitionManager.AlterPartDefinition("LocationsPart", builder => builder.Attachable());
//Creating the supplier. Specific supplier contentfields can be added later. Doing records, so I can add
//datafields later that are not contentfields
SchemaBuilder.CreateTable("SupplierPartRecord", table => table
.ContentPartRecord());
ContentDefinitionManager.AlterPartDefinition("SupplierPart", part => part
.Attachable(false)
);
ContentDefinitionManager.AlterTypeDefinition("Supplier", builder => builder
.Creatable()
.Draftable()
.WithPart("CommonPart")
.WithPart("TitlePart")
.WithPart("BodyPart")
.WithPart("AutoroutePart", partBuilder =>
partBuilder.WithSetting("AutorouteSettings.AllowCustomPattern", "true")
.WithSetting("AutorouteSettings.PatternDefinitions", "[{Name:'Supplier', Pattern: 'aanbieders/{Content.Slug}', Description: 'aanbieders/supplier-name'}]")
.WithSetting("AutorouteSettings.DefaultPatternIndex", "0"))
.WithPart("SupplierPart")
.WithPart("LocationsPart"));
return 1;
}
Models:
*LocationPartRecord and LocationPart *
public class LocationPartRecord:ContentPartRecord {
public virtual LocationsPartRecord LocationsPartRecord { get; set; }
}
public class LocationPart:ContentPart<LocationPartRecord> {
LocationsPartRecord LocationsPartRecord {
get { return Record.LocationsPartRecord; }
set { Record.LocationsPartRecord = value; }
}
}
LocationsPartRecord and LocationsPart (container)
public class LocationsPartRecord:ContentPartRecord {
public LocationsPartRecord()
{
Locations = new List<LocationPartRecord>();
}
[CascadeAllDeleteOrphan]
public virtual IList<LocationPartRecord> Locations { get; set; }
}
public class LocationsPart:ContentPart<LocationsPartRecord> {
public LocationsPart() {
Locations = new List<LocationPart>();
}
public readonly LazyField<IList<LocationPart>> _locations = new LazyField<IList<LocationPart>>();
public IList<LocationPart> Locations {
get { return _locations.Value; }
set { _locations.Value = value; }
}
}
From here I am stuck. I would like to see when Creating a new supplier, I get a screen containing all the content item fields for supplier and a list of locations, with the ability to create, delete or update a location.
I don't need the code to be spelled out, but a direction would suffice. Which drivers, controllers and views should I create. This is only for admin console. For frontend the locations need to be displayed and not edited.
I don't think there will be any way to get the functionality you're after without custom coding. As you have suggested, the comments module could be a good example to copy. The Controllers in the comments module are only to manage all of the comments in their own admin pages, separate to the content items they belong to. The edit / display of the comments is still provided through the drivers and handlers.
Using the Comments module analogy:
CommentsPart = AddressesPart - This would be added to your Supplier content type
CommentPart = AddressPart - This would be added to your Address content type
You could strip out a lot of the extra functionality that is included for managing comments and just copy the drivers, handlers, views and models for these two parts.
I have seen some gallery modules that may allow you to build these relationships through the admin interface, however I haven't used it myself:
http://gallery.orchardproject.net/List/Modules/Orchard.Module.Downplay.Mechanics
Address shouldn't be a part, it should be a field. This way, you can have more than one, and each can be named.
Don't know if this would be helpful (and the site appears to be down - but Google has a cached version if you are patient for it to load), but there is a good blog about exactly your situation. It's Skywalkers excellent Web Shop series. I believe Part 8 contains the code related to multiple addresses (uses Address and Addresses). This seems to involve your problem, and the code may be what you need.
In case you have trouble getting to the site, there is also a CodePlex repository for the code. Additionally, Bertrand's Nwazet Commerce module might have similar code.
I have a couple of tables and have defined relationships for them.
{Table Department} {Table Unit} {Table Branch}
A Department can have more than one branch, a branch can only belong to one department. I need to be able to get the department name, departmentid, branchname
Branch has an instance of departmentid in it.
How do I pull this in one ORM call?
class Model_Admin_Departments extends ORM
{
protected $_has_many = array('branches' => array ());
class Model_Admin_Branches extends ORM
{
protected $_belongs_to = array('departments ' => array());
I have also created the foreign key constraints on the db side with action cascade on delete. Could this cause problems or that is fine?
Assuming you have the right relationships declared you should be able to use the with(...) method on your ORM object.