I need to create N to N relation between ContentItems. I've read corresponding article in documentation. There are 3 types of relations:
1 to N relation between records
N to N relation between records
1 to N relation between Content Items with lazy loading.
I haven't found any manual for creating N-to-N relation between content items. I have:
ProfessionItem with ProfPart/ProfPartRecord
SpecialityItem with SpecPart/SpecPartRecord
So far I've only created N to N between records. I think I should create some kind of record like:
public class ContentProfSpecRecord {
public virtual int Id { get; set; }
public virtual ContentItemRecord Spec { get; set; }
public virtual ContentItemRecord Prof { get; set; }
}
but I'm little bit confused with all these Lazy fields. Should I add LazyField<IEnumerable<IContent>> to ProfPartRecord or not?
Any links to guides or any help will be appreciated.
thanks!
Related
I am evaluating Azure Search for a project. The MSDN articles are having only Flattened schema structure. Below is an example scenario i am looking at.
The below is "Project" class having reference to List of "Question" class. And "Question" has it's own set of fields
public class Project
{
public Guid Id
{
get;
set;
}
public string Owner
{
get;
set;
}
public string Title
{
get;
set;
}
public List<Question> QuestionList
{
get;
set;
}
public bool Disable
{
get;
set;
}
}
public class Question
{
public Guid Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
}
Below will be Index Schema for Project
Id - Edm.String
Owner - Edm.String
Title - Edm.String
QuestionList - Collection(Edm.String)
Questions
Is it possible to specify each item in QuestionList has hierarchical data?
Is it possible to Search only inside "Title" of "Question"?
The only possibility i see is to create Index for "Question" separately and use it
The only point i see in MSDN relevant is the below paragraph and i can't make much sense of it
Levels in faceted navigation
As noted, there is no direct support for nesting facets in a
hierarchy. Out of the box, faceted navigation only supports one level
of filters. However, workarounds do exist. You can encode a
hierarchical facet structure in a Collection(Edm.String) with one
entry point per hierarchy. Implementing this workaround is beyond the
scope of this article, but you can read about collections in OData by
Example.
For your first question, Azure Search does not allow for hierarchical datatypes, and to search you would need to flatten the data as you did for the QuestionList field which you created as a Collection. If you were asking how to also filter results based on items in this Collection, you can do that using OData Expressions such as $filter=QuestionList/any(t: t eq 'Question1') (https://msdn.microsoft.com/en-us/library/azure/dn798921.aspx)
I think for your second question, you were interested searching only in "Title" or "Question", correct? For this, you can use the SearchFields parameter (https://msdn.microsoft.com/en-us/library/azure/dn798927.aspx).
Liam
Imagine I have two "areas" in my API, inventory and orders. I can quite easily group all methods related to inventory into "/inventory/" and to orders "/orders/" routes.
However, when I go to the root page of API where all methods are shown (IndexOperations.html) all methods are mixed together into one big list.
Is there any way to group methods from different areas on that list? For example show something like this on the operations index page.
Inventory
Method1
Method2
Orders
Method1
Method2
Group your operations:
If you group your DTOs into a static class as shown below, then ordering will be taken care of automatically assuming you want the groups alphabetically.
public static class UserOperations
{
[Route("/Users","POST")]
public class CreateUserRequest
{
public string Name { get; set; }
public int Age { get; set; }
}
...
}
public static class DuckOperations
{
[Route("/Ducks","POST")]
public class CreateDuckRequest
{
public string Name { get; set; }
public int Age { get; set; }
}
...
}
Alternatively specify the sort:
The ServiceStack MetadataFeature in v4.09+ provides access to the IndexPageFilter which lets you specify specify the Sort function that is applied to the index pages' OperationNames, where the OperationName is the full type name of the DTO.
var metadata = Plugins.First(x => x is MetadataFeature) as MetadataFeature;
// This is the default sort, replace with one that groups
metadata.IndexPageFilter = (page) => page.OperationNames.Sort((a,b) => b.CompareTo(a));
I hope this helps.
Allright, this should be fairly easy.
I would like to persist some records for my module in Orchard (1.7.2) without those records being also a ContentPartRecord.
In other words, I would like to be able to persist in DB the following objects:
public class LogItemRecord
{
public virtual string Message { get; set; }
}
..which is already mapped on to the db. But notice that this class is not derived from ContentPartRecord, as it is most certainly not one.
However, when I call IRepository instance's .Create method, all I get is a lousy nHibernate exception:
No persister for: MyModule.Models.LogItemRecord
...which disappears if I do declare the LogItem record as having been inherited from ContentPartRecord, but trying to persist that, apart from being hacky-tacky, runs into an exception of its own, where nHibernate again justly complains that the Id value for the record is zero, though in not so many words.
So... how do I play nicely with Orchard and use its API to persist objects of my own that are not ContentParts / ContentItems?
I'm running 1.7.3 (also tested in 1.7.2) and have successfully been able to persist the following class to the DB:
public class ContactRecord
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual string JobTitle { get; set; }
public virtual string Email { get; set; }
public virtual string Phone { get; set; }
}
Here are the relevant lines from Migrations.cs
SchemaBuilder.CreateTable(
typeof(ContactRecord).Name,
table => table
.Column<int>("Id", col => col.Identity().PrimaryKey())
.Column<string>("Name")
.Column<string>("JobTitle")
.Column<string>("Email")
.Column<string>("Phone")
);
I'm going to assume that the code you've shown for LogItemRecord is the complete class definition when making the following statement...
I think that any Record class you store in the DB needs an Id property, and that property should be marked as Identity and PrimaryKey in the table definition (as I've done above).
When you create a *Record class which inherits from ContentPartRecord and setup the table like
SchemaBuilder.CreateTable(
"YourRecord",
table => table
.ContentPartRecord()
// more column definitions
);
then you get the Id property/PK "for free" by inheritance and calling .ContentPartRecord() in the Migration.
See the PersonRecord in the Orchard Training Demo Module for another example of storing a standard class as a record in the DB.
here are my entities:
public abstract class ResourceBase
{
[Key]
int Id { get; set; }
[ForeignKey("Resource")]
public Guid ResourceId { get; set; }
public virtual Resource Resource { get; set; }
}
public class Resource
{
[Key]
public Guid Id { get; set; }
public string Type { get; set; }
}
public class Message : ResourceBase
{
[MaxLength(300)]
public string Text { get; set; }
}
And then my query is something like this:
var msgs = messages.Where(x=>x.Id == someRangeOfIds).Include(m=>m.Resource).Select(x => new
{
message = x,
replyCount = msgs.Count(msg => msg.Id = magicNumber)
});
I am running this with proxy creation disabled, and the result is all the messages BUT with all the Resource properties as NULL. I checked the database and the Resources with matching Guids are there.
I drastically simplified my real life scenario for illustration purposes, but I think you'll find you can reproduce the issue with just this.
Entity Framework 5 handles inherited properties well (by flattening the inheritence tree and including all the properties as columns for the entity table).
The reason this query didn't work was due to the projection after the include. Unfortunately, the include statement only really works when you are returning entities. Although, I did see mention of a solution which is tricky and involves invoking the "include" after the shape of the return data is specified... If anyone has more information on this please reply.
The solution I came up with was to just rephrase the query so I get all messages in one query, and then in another trip to the database another query that gets all the reply counts.
2 round trips when it really should only be 1.
I'm using Entity Framework 4.3 code first. How do I create two "one to many"-relationships between two properties in class A and a collection in class B?
My model:
public class Shaft
{
public int Id { get; set; }
public virtual Coupling FirstEnd { get; set; }
public virtual Coupling SecondEnd { get; set; }
}
public class Coupling
{
public int Id { get; set; }
public virtual ICollection<Shaft> Shafts { get; set; }
}
Well, a one-to-many relationship is called one-to-many because there is one element on the first end of the relationship and many elements on the other end. You also can have a zero or one-to-many relationship which only means that the element on the not-many side can be null (or NULL in the database).
What you are trying to define is a two-to-many (or perhaps zero or one or two-to-many) relationship. Such a thing does not exist in a relational database nor does it exist in Entity Framework.
When you define a relationship with EF you always need pairs of two navigation properties in source and target class. It is possible to omit one of the navigation properties but that does not mean that you can move the end of this relationship to another navigation property that already belongs to another relationship.
In your specific case you have two relationships because your two navigation properties FirstEnd and SecondEnd in Shaft represent two different foreign keys. Therefore you either need two collections in Coupling or you can relate the existing property Coupling.Shafts to either FirstEnd or SecondEnd but not to both. The other reference would refer to an "invisible" not exposed navigation collection in Coupling. (This is what will happen with the mapping in your own answer: EF will take the second mapping block that overwrites the first one, create a relationship between SecondEnd and Shafts and then another relationship between FirstEnd and a not exposed relationship end in Coupling, not Shafts again.)
The solution with two collections - which makes more sense in my opinion - would look like this:
public class Coupling
{
public int Id { get; set; }
public virtual ICollection<Shaft> ShaftsWithFirstEndHere { get; set; }
public virtual ICollection<Shaft> ShaftsWithSecondEndHere { get; set; }
}
And this mapping:
modelBuilder.Entity<Coupling>()
.HasMany(x => x.ShaftsWithFirstEndHere)
.WithOptional(x => x.FirstEnd);
modelBuilder.Entity<Coupling>()
.HasMany(x => x.ShaftsWithSecondEndHere)
.WithOptional(x => x.SecondEnd);
You can create a readonly and not mapped helper property to concatenate the two collections togother to one collection, but this concatenation will happen in memory after the two navigation collections already have been loaded:
public class Coupling
{
public int Id { get; set; }
public virtual ICollection<Shaft> ShaftsWithFirstEndHere { get; set; }
public virtual ICollection<Shaft> ShaftsWithSecondEndHere { get; set; }
// not mapped to DB because it has only a getter = readonly
public IEnumerable<Shaft> Shafts
{
get { return ShaftsWithFirstEndHere.Concat(ShaftsWithSecondEndHere); }
}
}
There is no kind of mapping which would do such a concatenation automatically. Be aware that a navigation collection property in a one-to-many relationship is just the result of a query by a foreign key in the dependent table (= Shaft in your example). The foreign key which is used to populate a collection (by using Include for example or when lazy loading is triggered) is well defined by the relationship mapping and it is only one key - either the key for FirstEnd or the key for SecondEnd but not both. What you are trying to achieve is the combined concatenated result of two queries by two different foreign keys. And that's not possible with relationship mapping.