Entity Framework--Filter Data At Load Time - asp.net-mvc-3

I’m building an MVC3 application with form authentication and a single hierarchical entity. The entity has a Region object as the “root” with several other objects. It looks something like:
Region->Language->objectA->objectB
Region->Application->….
Each user (other than administrators) is associated with single region. I'd like to limit the data loaded to the entity based on the user’s region. I’m not too familiar with EF. Is this appropriate or is there a better approach? How would I implement the best approach

You can certainly filter the data returned via Entity Framework. The code would look something like this:
using (MyContext ctx = new MyContext())
{
var filtered = (from r in ctx.Regions where SOME_CONDITIONS select r);
// Do stuff with filtered (which is an IEnumerable<Region>)
}
Note that you may need to use Include to load related objects, e.g.
ctx.Regions.Include("Language").Include("Application")
see http://msdn.microsoft.com/en-us/library/bb896272.aspx

Related

Eager loading for reference

I wonder if it is possible to load reference data in the first call. In my case I want to load the patient reference in the Encounter Resource. As I know I always need the patient data I want to avoid to to do an additional call to get the patient data.
The server is HAPI FHIR and the client firely .Net API
Yes, that is possible. Your request will have to be a search, that way you can include any referenced resources.
On REST level it looks like this:
GET <hapi_server>/Encounter?_include=patient
Add any filters you have. For example if you have a specific encounter you would add &_id=<technical_id>.
With the FhirClient from the .Net api, the code looks like this:
var c = new FhirClient("<hapi_server");
var q = new SearchParams().Include("Encounter:patient");
q.Add("_id", "<technical_id>");
var result = c.Search<Encounter>(q);

How to access View Template Properties for Revit and compare them in Real Time?

I am trying to list the view template’s properties so we can compare them with another old template.
For example what model elements are hidden or have overrides in a given template or which Revit links have been hidden or overridden in a given template.
View Template
(https://www.google.com/search?q=view+template+revit&rlz=1C1GGRV_enUS770US770&source=lnms&tbm=isch&sa=X&ved=0ahUKEwjLndrd2cTbAhVESq0KHX1cAPwQ_AUICygC&biw=1536&bih=824#imgrc=Q0v-pV7Nxl4kfM:)
I’m looking to devise a View Template Compare tool and access to the owner and creator of them.
public void ApplyViewTemplateToActiveView()
{
Document doc = this.ActiveUIDocument.Document;
View viewTemplate = (from v in new FilteredElementCollector(doc)
.OfClass(typeof(View))
.Cast<View>()
where v.IsTemplate == true && v.Name == "MyViewTemplate"
select v)
.First();
using (Transaction t = new Transaction(doc,"Set View Template"))
{
t.Start();
doc.ActiveView.ViewTemplateId = viewTemplate.Id;
t.Commit();
}
}
With Revit API you can access with:
GetTemplateParameterIds Method / ViewTemplateId Property
The Revit API exposes almost all the ViewTemplate properties.
For instance this method returns all the Visibility/Graphic Overrides for a specific category:
https://apidocs.co/apps/revit/2019/ed267b82-56be-6e3b-0c6d-4de7df1ed312.htm
The only thing I couldn't get for a ViewTemplate are the "includes", but all the rest seems to be there.
Update:
The list or properties "not included" can be retrieved with GetNonControlledTemplateParameterIds().
Yes, and no.
Yes, I guess you can use Forge Model Derivative API to export RVT file and then build a dashboard around the View Templates data. That's assuming that View Templates data actually gets exported when the model is translated. That data is not attached to any geometry so I would not be surprised if it was skipped. The question here is why? This is like renting a 16-wheel truck to move a duffel bag across the street.
No, if your intention is to directly interact with the RVT model. Forge can view it, but to push anything back or request changes to the model, is not available yet. Then again, I am not even sure that the view template data is available via model derivative exports.
This brings me another alternative. Why not just collect the data using Revit API, the standard way and then push it out to a Database and build on top of that? There is no reason to employ Forge for any of that.
Thanks Jeremy, I had dig into your amazing website and also some solution that Konrad post in the Dynamo Forum about this. In Revit seems pretty achievable, you filter the View that is View Template and then extracts these properties, is it correct?.
I am wondering if someone can point me in the right direction with Forge.
Some amazing guys are developing a BQL https://www.retriever.works/.
BQL(Building Query Language) is a query language for buildings, similar to how SQL is a query language for databases. It is fast and flexible. BQL helps improve efficiency for QA/QC (quality assurance and quality control), and building data extraction without leaving Revit. I am also trying these and I would like to understand if there are some works where I could start with Forge next week about this.

Is there a way to add a filter to the Entity Framework layer to exclude "IsArchived" records?

I have records marked up as "IsArchived". I am looking for an expedient way to exclude these records from a current MVC3 / EF3 web application.
Is there a way to add some kind of "IsArchived" filter to the EF layer. In my case I have a seperate Model project with tables/views represented as POCO entities, and the mappings contained in the CSDL and SSDL files.
Huge thanks for any assistance.
EDIT:
I am using "ObjectContext" and not "DbContext", mainly due to the Data Modelling tool that I am using. This tool creates the context and POCO files.
I am wondering whether I can edit this context file like the following:
public ObjectSet<StdOrg> StdOrg
{
get
{
if ((_StdOrg == null))
{
_StdOrg = base.CreateObjectSet<StdOrg>("StdOrg");
// new line below. Got cast error tween both sides.
_StdOrg = (ObjectSet<StdOrg>) _StdOrg.Where(r => r.IsArchived == false);
}
return _StdOrg;
}
}
Take a look at this http://www.matthidinger.com/archive/2012/01/25/a-smarter-infrastructure-automatically-filtering-an-ef-4-1-dbset.aspx
Basically a filtering DBSet implementation that the example basically shows being used for Soft Delete. We use it without issue in our App.
However we are using DBcontext so not sure how this would work with Object Context or how it could be adapted

Linq lazy loading, (EF Code first, Web.API and MVC)

I am having an odd problem with data loading which I don't understand, and I am hoping someone can explain to me what is going on, and perhaps how to accomplish my task more directly.
I am building a website using the technologies listed in the subject of this question.
I have a set of objects - each object has several properties (Name, ID, etc.) and a collection (ICollection<>) of other objects. So just looking at the tree of objects and their collections, it looks like this:
Tab
-TabRows
--Sections
---SectionRow
----Article
(So each tab has one or more tabrows, each tabrow has one or more sections, and so on. Each sub-object has a link back the parent, so each sectionrow has a SectionID, each Section has a TabRowID, etc.)
OK, so given that structure, consider this code:
// GET api/Tab/5
public Tab GetTab(int id)
{
var tab = db.Tabs.FirstOrDefault(t => t.TabId == id);
var tabrows = db.TabRows.ToList();
var sections = db.Sections.ToList(); // This makes the tabRow.Sections populate
var sectionrows = db.SectionRows.ToList();
var articles = db.Articles.ToList();
return tab;
}
So here is what happens. When the first line (var tab =...) executes, I get a tab object, but the TabRows collection is empty. (It is not null because the constructor instantiates it).
When the second line (var tabrows =...) executes, tab.TabRows suddenly populates. tab.TabRows.Sections is empty.
When the third line executes, tab.TabRows.Sections suddenly populates.
And so on.
I am assuming this is some sort of "lazy loading" on behalf of Linq, or perhaps one of the other technologies. But I don't know them well enough to figure it out.
Is there a way to re-write this so that I can just call line 1 and basically have everything auto-populate without having to individually reference every single object in every single collection?
Lazy loading is enabled by default and eager loading disabled. Entity framework allows you to hint at eager loading using the include statements. Your statement will become something like this.
var tab = db.Tabs.FirstOrDefault(t => t.TabId == id).Include("TabRows");
or as Include(t => t.TabRows);
Take a look at this link for more information.
In your case you would need to handle nested includes as well. Which means you would be better off taking another Model (your class) structured as follows
Tabs -> Containing a List<TabRows> -> containing a List<Sections> etc.
You would then need to re-write the linq so it populates the entire Model including the nested entities using nested includes.
As a side note, too many of these inner joins might slow down your querying and so consider indexed views on your DB side if and when possible

How can I force a complete load along a navigation relationship in Entity Framework?

Okay, so I'm doing my first foray into using the ADO.NET Entity Framework.
My test case right now includes a SQL Server 2008 database with 2 tables, Member and Profile, with a 1:1 relationship.
I then used the Entity Data Model wizard to auto-generate the EDM from the database. It generated a model with the correct association. Now I want to do this:
ObjectQuery<Member> members = entities.Member;
IQueryable<Member> membersQuery = from m in members select m;
foreach (Member m in membersQuery)
{
Profile p = m.Profile;
...
}
Which halfway works. I am able to iterate through all of the Members. But the problem I'm having is that m.Profile is always null. The examples for LINQ to Entities on the MSDN library seem to suggest that I will be able to seamlessly follow the navigation relationships like that, but it doesn't seem to work that way. I found that if I first load the profiles in a separate call somehow, such as using entities.Profile.ToList, then m.Profile will point to a valid Profile.
So my question is, is there an elegant way to force the framework to automatically load the data along the navigation relationships, or do I need to do that explicitly with a join or something else?
Thanks
Okay I managed to find the answer I needed here http://msdn.microsoft.com/en-us/magazine/cc507640.aspx. The following query will make sure that the Profile entity is loaded:
IQueryable<Member> membersQuery = from m in members.Include("Profile") select m;
I used this technique on a 1 to many relationship and works well. I have a Survey class and many questions as part of that from a different db table and using this technique managed to extract the related questions ...
context.Survey.Include("SurveyQuestion").Where(x => x.Id == id).First()
(context being the generated ObjectContext).
context.Survey.Include<T>().Where(x => x.Id == id).First()
I just spend 10mins trying to put together an extention method to do this, the closest I could come up with is ...
public static ObjectQuery<T> Include<T,U>(this ObjectQuery<T> context)
{
string path = typeof(U).ToString();
string[] split = path.Split('.');
return context.Include(split[split.Length - 1]);
}
Any pointers for the improvements would be most welcome :-)
On doing a bit more research found this ... StackOverflow link which has a post to Func link which is a lot better than my extension method attempt :-)

Resources