MDX object not found in cube - mdx

I have districts with areas. and i'm trying to fetch data from my cube. the problem is:
i add new area to district in database.
the data in cube is recalculated only once a day. so rigth after i have added new area it will be not present in my cube.
and when i try to get info from cube i get the error 'MDX object '[ATD].[Area].&[6007d9a7-a137-4bba-9d72-0020ee5d2db0]' not found in cube'
after the cube is recalculated everything is ok.
how can i fight this error?
with member [Measures].[District]
member [Measures].[Area]
member [Measures].[AreaID]
select
{
[Measures].[District],
[Measures].[Area],
[Measures].[AreaID]
} on columns,
{
{{[MyDimension].[Area].&[6007d9a7-a137-4bba-9d72-0020ee5d2db0]}}
} on rows
from SomeCube
Thanks in advance.

You should set the ignoreInvalidMembers property to true.
You can find more information on Mondrian's configuration page.

Related

How to get user from User field LookupId

I have a list in sharepoint online.
And in this list, i have a person field.
When i call the API endpoint to get all the items in the list, i get an LookupId value for the person field.
I tried to get the user by using the value of the lookupid, but it don't work because the id is not recognized.
The lookupid is a int (eg: 21) instead of a guid.
Is there something missing in the configuration of the person field or in my calls to Microsoft Graph API ?
When a user signs into a SharePoint site collection for the first time, a ListItem is created in a hidden User Information List. The LookupId in a PersonOrGroup field refers to the ListItem in this list. The URL for the User Information List for SharePoint Online should be:
https://{yourTenant}.sharepoint.com/{yourSiteCollection}/_catalogs/users/detail.aspx
Since the User Information List is a generic SharePoint list, you can query the list via Graph. First, get the list id for the User Information List. An easy way to get the list id is to view the source for the User Information Site via Chrome and search for 'listId'. You should find a result like this:
"listId":"{yourListIdIsHere}"
Copy the id. By using the copied id, the id of your root site and the LookupId, you can get the ListItem in the User Information List:
https://graph.microsoft.com/v1.0/sites/{siteId}/lists/{pasteCopiedListId}/items/{lookUpId}?$expand=Fields
The ListItem contains information about the user, such as the email, which can be used to identify the Azure user:
https://graph.microsoft.com/v1.0/users/{eMail}
Question: How could i get the hidden User Information List from Microsoft Graph?
If you do not want to use the 'trick' with Google Chrome to get the id, there is another way to get the site. Typically, if you want to get the id for any site, you would call:
https://graph.microsoft.com/v1.0/sites/{siteId}/lists
However, you will not find the id of the User Information List, even if you include hidden sites. I do not know why. An additional problem seems to be, that you cannot filter lists by their name:
https://graph.microsoft.com/v1.0/sites/{siteId}/lists?$filter=name eq 'users'
The query returns an error, that the provided filter statement is not supported. The only way to get the list without knowing the id seems to by using the property displayName of the list. However, the displayName is based on your localization. So, since I am from Germany, I can get the site by using the query:
https://graph.microsoft.com/v1.0/sites/{siteId}/lists?$filter=displayName eq 'Benutzerinformationsliste'
You will need to replace Benutzerinformationsliste with your localized name. For EN replace it with 'User Information List'.
This returns the expected result:
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#sites('xxx')/lists(id,name,displayName)",
"value": [
{
"#odata.etag": "\"xxx\"",
"id": "xxx",
"name": "users",
"displayName": "Benutzerinformationsliste"
}
]
}
As you can see, the name of the list is 'users', so why the first filter statement does not work is a little mystery to me. Maybe someone here knows and can help out.
Some of the queries above don't work at the moment.
What I finally found as a good solution - after trying many many queries - is that you can do this by following the few steps below:
1- Get the GUID of the user information list.
Using the title of the list "User Information List" or the name "users" in the parameter "$filter" does not work.
Don't forget 'system' among the properties you select if you want to retrieve the hidden system-lists.
GET https://graph.microsoft.com/v1.0/sites('{site_id}')/lists?select=id,name,system
2- Filter the previous result in order to pick up the ID of the targeted list named 'users'.
By the way, applying this restriction "$filter=name eq 'users'" does not work.
You will get an exception. So you must do the filtering part by writing a few lines of code.
3- Once you've got the list identifier, then select all the items you want. And voilĂ ! The word 'Fields' must be in pascal case (uppercase the first letter ).
GET https://graph.microsoft.com/v1.0/sites('{site_id}')/lists('users_list_id')/items?$select=Fields&$expand=Fields
As #QuestionsPS1991 mentioned, the people field in fact refers to the hidden user list. With the lookupid, we can get the user via below methods:
Get user by id
Get user property by expanding lookup field
//////////// updated
By default, MS Graph does not return this user list. You may hard code the list id or follow ##QuestionsPS1991 suggestion. Below is my test:

IcCube Reporting : How to stop drill in a hierarchy?

When we query a dimension/hierarchy with multiple levels, the drill is by default allowed thru all the levels of that hierarchy...
For example, in a hierarchy made of : Continent/Country/State/City.
What is the solution to restrict the drill to the State level (i.e. not showing the city level) without having to create a new hierarchy without City ?
I heard that this can be done using fonctions in the schema scripts to "flatten" the hierarchy.
Can someone give me a live example of that ?
The first is mapping our navigation as an MDX function (you could also copy&paste the code but there is no reuse). Somethink like this (Sales example) :
CREATE FUNCTION navigationDemo(_x) AS
{
CASE
WHEN _x.hierarchy is [Customers].[Geography] THEN [Product].[Product].[Category]
WHEN _x.hierarchy is [Product].[Product] THEN [Time].[Year].[Year]
ELSE {}
END
}
Once this is done we can go to our widget, in our example a table, and define a Drilldown Strategy. It should be of type mdxExpression and we can insert into the MDX Expression our newly created function
navigationDemo( $member ) // where $member is the clicked member in the table
Do no forget to set the 'Filter by' as we want the new data to be filtered by the clicked member.

Checking if certain key exists in database

I have saved certain MDX query and I run them using ADOMD.NET. I get CellSet back which I convert into dataset. All this is working fine. Now the DB team has changed the cube structure. They have updated the DimesnionName, Attribute Name etc. Some dimensions got renamed and some got deleted. Becuase of this I am unable to run my saved queries. I want to create a console application, which will take list of keys ([DimensionName].[AttributeName] or [DimensionName].[AttributeName].[MemeberName] format) and it will tell me following keys does not exists.
Please let me know if this is possible programatically. I dont want to check it manually.
Kindly share a link or code which will help me acheive this.
Thank you.
If you're using ADOMD already this should be no problem, just use the metadata queries:
http://msdn.microsoft.com/en-us/library/ms123485.aspx
Alternatively, AMO is nice http://msdn.microsoft.com/en-us/library/microsoft.analysisservices.aspx
I use it in SSIS for processing, you could easily use it in .Net to test existence of elements:
using Microsoft.AnalysisServices;
...
Server server = new Server();
server.Connect(cubeConnectionString);
Database database = server.Databases.FindByName(databaseName);
Cube cube = database.Cubes.FindByName(cubeName);
foreach (MeasureGroup measureGroup in cube.MeasureGroups)
{
foreach (Partition partition in measureGroup.Partitions)
{
...
}
}
foreach (CubeDimension cubeDimension in cube.Dimensions)
{
Dimension dimension = cubeDimension.Dimension;
var dimName = dimension.Name;
...
}
Finding the names in advance for all the elements you need is probably the hard part (And keeping it all up-to-date).
Would it not be easier to fire all the queries at the cube and try to trap the "no such thing" response?

Editing User Profile Data in SimpleMembership

I am using SimpleMembership in an MVC4 web app. I can't figure out how to edit the profile information. I thought I could do it just as you do any other table.
[HttpPost]
public ActionResult EditUser(UserProfile user)
{
if (ModelState.IsValid)
{
udb.Entry(user).State = EntityState.Modified;
udb.SaveChanges();
return RedirectToAction("Index");
}
But I get an error saying entity state does not exist in the current context. My context is defined as follows at the top of the controller.
private UsersContext udb = new UsersContext();
I can find plenty of references on access profile data but nothing for editing the data. How can I save the edited UserProfile data back to the db?
EDIT: I was able to resolve the entityState error -- I had to include system.data and system.data.entity. However now when I run I get an error on edit which says unexpected number of rows modified (0). and points to the udb.SaveChanges() line. Still can't figure out how to modify UserProfile data elements.
Simple answer. I needed to set all the fields for the Model in my view. I was only allowing the user to change 4 out of the 6 so two were not being set.
I thought when you pass the model to the view, the view would pass the same field values onto the action if they were not set in the view. For example: if I set FirstName in the view but not UserName the original UserName that was sent to the view would be passed to the Model. That appears not to be the case. For all the items in the model I did not allow them to change in the view I had to set hidden fields to set the fields so a complete model was sent.
It may be better to set individual fields but I am not sure how to do that yet and that was not the question.

How to use display method as a range in axapta 3.0 report

I am just wondering if someone could help me please. I am designing a report in Axapta 3.0 and facing a issue. I have got a display method in InventTable which is returning the ON-Hand stock quantity. I am using this in a report to show the quantity of item has not been sold. Now i want to add this method as a range so only the item has quantity more then 5 on hand should be displayed.
I will appreciate any help regarding this.
Regards,
As I know you cannot use method as range.
Range is a database-side logic. Axapta core converts all ranges to valid SQL and transfer it to database server.
Table method is a AOS (or client) logic. It works on AOS or client. It cannot be converted to SQL and tranfered to database server.
But you can fetch all records from database server and filter them on AOS (or client) in your report code. Just override fetch() or send() method on your report to do it.
Here you can find the example.
Another workaround that doesn't require overwriting the fetch method. You can try overwriting the executeSection method (e.g.
\Reports\YourReport\Designs\ReportDesign1\AutoDesignSpecs\Body:YourReportBody\Methods\executeSection) in the following way:
public void executeSection()
{
InventQty qty = yourMethodToCalculateQty();
;
if (qty > 5)
{
super();
}
}
If the quantity is not greater than 5 the line will be skipped.