I am using report builder 3.0 to create reports in a vendor's environment where I only have access to their data sources. We have static data that we need to use in conjunction with the datasets we are creating from their models and I am trying to figure out how to add our data to a report to use for looking up values.
For Example:
The data set has AccountNo, OrderNo, ItemNo, Quantity, etc.
I need to be able to show some attributes about the ItemNo, like ItemName, ItemCost, ItemValue, etc.
I would like to have a dataset I can lookup against to get these values, but the only way I can get this to work is to create a report code function with hundreds of thousands of IF statements: IF ItemNo = "12345" Then ItemName = "XYZ Product"
This is slow and cumbersome to say the least. If the data sources were under my control, I could simply add a table in SQL, but I cannot in this environment. I have even tried linking to external datasource and that is not allowed by the environment. I am looking into creating some kind of XML data or trying to add data directly to the RDL, but I am running out of options.
Does anyone know of a any way to add a set of data or create an embedded dataset that contains static values. Any help would be greatly appreciated.
Thank you in advance,
Eric.
You could add a shared dataset that uses a table variable. So just create a new shared dataset and use a query like
DECLARE #t TABLE(ItemNo int, ItemName varchar(100))
INSERT INTO #t VALUES
(12345, 'XYZ Product'),
(23456, 'ABC Product')
SELECT * FROM #t
You could use this in each report and do a lookup to it to get the data you require.
Hopefully you have enough access to create a shared dataset, if not you would have to copy this to each report but it will be faster than thousands of IIFs
You could code this in VBA in the custom code section of the report. And/or make this a custom DLL which can source the data from wherever you want. The lookup code would be contained in the custom DLL in that case (pass in an input and the code returns the lookup).
Create a Data Source of Type XML
Create a Data Set and set the Data Source Created at step 1
Set Query Type to Text
Add some XML there is an example below
You should now see 3 columns in your output, I know its late but I was searching for this myself and hopefully will help someone else
<Query>
<XmlData>
<?xml version="1.0"?>
<Months>
<Month MonthValue="1">
<Name="January" />
<ShortName="Jan" />
</Month>
<Month MonthValue="2">
<Name="February" />
<ShortName="Feb" />
</Month>
<Month MonthValue="3">
<Name="March" />
<ShortName="Mar" />
</Month>
<Month MonthValue="4">
<Name="April" />
<ShortName="Apr" />
</Month>
<Month MonthValue="5">
<Name="May" />
<ShortName="May" />
</Month>
<Month MonthValue="6">
<Name="June" />
<ShortName="Jun" />
</Month>
<Month MonthValue="7">
<Name="July" />
<ShortName="Jul" />
</Month>
<Month MonthValue="8">
<Name="August" />
<ShortName="Aug" />
</Month>
<Month MonthValue="9">
<Name="September" />
<ShortName="Sep" />
</Month>
<Month MonthValue="10">
<Name="October" />
<ShortName="Oct" />
</Month>
<Month MonthValue="11">
<Name="November" />
<ShortName="Nov" />
</Month>
<Month MonthValue="12">
<Name="December" />
<ShortName="Dec" />
</Month>
</Months>
</XmlData>
</Query>
Related
I have this SQL query where I am trying to fetch the opportunityId from opportunity entity for whom approvaldocument has not been created (approval document is the name of the other entity) .I dont think fetchxml supports such kind of query. I am new to crm and my project is in crm 4.0 version.
here's the sql query:
Select OpportunityId from opportunity AS c left JOIN (select a.opportunitynameid from opportunity o
JOIN ApprovalDocument a ON
a.opportunitynameid=o.OpportunityId) AS b ON c.OpportunityId=b.opportunitynameid
Where b.opportunitynameid IS NULL and statecode=0
I converted this into a fetchxml, but that didn't give the correct result.
<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="true">
<entity name="opportunity"> <attribute name="opportunityid" />
<link-entity name="approvaldocument" from="opportunitynameid" to="opportunityid" alias="a" link-type="outer"> <attribute name="opportunitynameid" />
</link-entity>
<filter type="and">
<condition entityname="a" attribute="opportunitynameid" operator="null" />
</filter>
</entity>
<fetch/>
Natively it is not possible to create an advanced find to query for the absence of a relationship. However there are several different solutions for achieving this functionality:
Workaround:
Create a marketing list with the full set of records and then remove records using the inverse of your condition. The steps for doing this are nicely laid out in this article.
Modifying FetchXML and Third Party Solutions:
Although the advanced find cannot show "Not In" results, the underlying FetchXML does support this functionality. An example of manually building such Fetch is shown here. Also there are several third party tools which leverage this ability to provide Not In functionality directly in the advanced find. The best solution I am aware of is available here.
so, i was trying to implement a stored procedure with multiple results sets in entity framework.
it all seemed to be too easy.
but, i am not getting any rows for my results sets (even though, it seems i do get the result sets themselves back).
What i have done:
created the stored procedure which returns 3 result sets
Created the complex type that represents the return values
manually edited the edmx file as per Stored Procedures with Multiple Result Sets
Failed with 3 and tried the code version from the same page, still no rows back.
Reverted the code back to 3.
my edmx file (related content only):
<FunctionImport Name="getGlobalReport2">
<ReturnType Type="Collection(MTModel.GlobalReport2)"/>
<ReturnType Type="Collection(MTModel.GlobalReport2)"/>
<ReturnType Type="Collection(MTModel.GlobalReport2)"/>
<Parameter Name="regions" Mode="In" Type="String" />
<Parameter Name="countries" Mode="In" Type="String" />
<Parameter Name="companySizes" Mode="In" Type="String" />
<Parameter Name="products" Mode="In" Type="String" />
</FunctionImport>
<FunctionImportMapping FunctionImportName="getGlobalReport2" FunctionName="MTModel.Store.getGlobalReport2" >
<ResultMapping>
<ComplexTypeMapping TypeName="MTModel.GlobalReport2" />
</ResultMapping>
<ResultMapping>
<ComplexTypeMapping TypeName="MTModel.GlobalReport2" />
</ResultMapping>
<ResultMapping>
<ComplexTypeMapping TypeName="MTModel.GlobalReport2" />
</ResultMapping>
</FunctionImportMapping>
my code:
var x = mtEntities.getGlobalReport2(regions, countries, companySizes, products);
Response.Write(x.Count());
var y = x.GetNextResult<GlobalReport2>();
Response.Write(y.Count());
var z = x.GetNextResult<GlobalReport2>();
What i have allready checked:
Checked that the server receives the request as per How can I view live MySQL queries?
Run the query i grabbed from the server and made sure it returns result sets and rows
Debug the app to see there are no Exceptions i missed on the way
There seems to be no issue with the call, or the app, except that no rows are returned.
Any suggestions?
EDIT:
as per your comments about the edmx being overwritten, that would happen only if i regenerate the model from the database, not if i update it.
i wouldn't expect anything else, since its regenerating the model.
Dont you think you should have some property defined for your complex types you have created ? For example:
<FunctionImportMapping FunctionImportName="GetGrades"
FunctionName="SchoolModel.Store.GetGrades" >
<ResultMapping>
<ComplexTypeMapping TypeName="SchoolModel.GradeInfo">
<ScalarProperty Name="EnrollmentID" ColumnName="enroll_id"/>
<ScalarProperty Name="CourseID" ColumnName="course_id"/>
<ScalarProperty Name="StudentID" ColumnName="student_id"/>
<ScalarProperty Name="Grade" ColumnName="grade"/>
</ComplexTypeMapping>
</ResultMapping>
</FunctionImportMapping>
Check this too
Also as rightly stated by Mike in the comment to your question, if you in future update your edmx file, if it's regenerated you're going to lose to customizations.
I am making a web application and have a webform connected to an access database table. For one of my queries I have a table with supplier info and I need to filter the results by name, city, and type.
I used the query builder to have the parameters input by the user through 3 textboxes (one for each parameter). When I run the query in the query builder the results come up fine, but when I run it through a browser it fails (the form shows up fine, but it's not taking the input parameters in the textbox to populate the table). I made sure I linked the parameters to the texbox control through the wizard.
I've built forms with a single input parameter controlled with a single textbox and those have worked just fine, but when I used multiple parameters and textboxes it doesn't work in the browser.
I appreciate any help! Thanks!
Make sure you bind control with parameter.
<SelectParameters>
<asp:ControlParameter Name="Comments" PropertyName="Text" Type="String" />
<asp:ControlParameter ControlID="txtLastName" Name="Title" PropertyName="Text" Type="String" />
</SelectParameters>
You can pass parameters runtime as below.
<SelectParameters>
<asp:Parameter Name="Comments" Type="String" />
<asp:Parameter Name="Title" Type="String" />
</SelectParameters>
protected void AccessDataSource1_Selecting(object sender, System.Web.UI.WebControls.SqlDataSourceSelectingEventArgs e)
{
if (txtFirstName.Text.Length > 0 && txtLastName.Text.Length > 0)
{
e.Command.Parameters["parameter1"].Value = txtFirstName.Text;
e.Command.Parameters["parameter2"].Value = txtLastName.Text;
}
}
I need an idea/tip how to use DbUnit to assert IDs, generated by a database (e.g. MySQL's auto increment column). I have very simple case, which yet, at the moment, I find problematic:
2 tables: main and related. main.id column is an auto-increment. Related table has a foreign key to it: related.main_id -> main.id. In my test case my application does insert multiple entries into both tables, so the dataset looks similar to this:
<dataset>
<main id="???" comment="ABC" />
<main id="???" comment="DEF" />
<related id="..." main_id="???" comment="#1 related to ABC" />
<related id="..." main_id="???" comment="#2 related to ABC" />
<related id="..." main_id="???" comment="#3 related to DEF" />
<related id="..." main_id="???" comment="#4 related to DEF" />
</dataset>
As the order, how the inserts will be performed is unclear - I cannot simply clear/truncate the table before the test and use predefined IDs in advance (e.g. "ABC" entry will come at first so it gets ID 1 and "DEF" as 2nd - gets 2). If I write test such way - this will be wrong - with a bit of luck sometimes it may work and in other cases not.
Is there a clean way how test such cases? As I still want to assert that entries were created and linked properly in DB, not only that they exists (if I would simply ignore the auto-increment columns).
Based on the comments of the question, I am answering my own question, so this may help others, looking for similar solution.
After all we did skip asserting generated IDs, as they were not really interesting for us. What we actually did want to check is that the entries between main and related tables are "properly linked". To achieve this, in our unit test we did created the the dataset using query, joining both tables:
SELECT main.comment, related.comment AS related_comment
FROM main, related
WHERE main.id = related.main_id
Then we assert, that dataset produced by this query matches statically defined dataset:
<dataset>
<result comment="ABC" related_comment="#1 related to ABC" />
<result comment="ABC" related_comment="#2 related to ABC" />
<result comment="DEF" related_comment="#3 related to DEF" />
<result comment="DEF" related_comment="#4 related to DEF" />
</dataset>
When the datasets are matching, we can assume, that entries were "linked properly".
Maybe you let dbunit sort your table main by id and table related by id automatically. Since the absolute number of rows are known in advantage this should solve your problem.
DBUnit allows sorting with org.dbunit.dataset.SortedTable.SortedTable which needs a table an a list of colums which should be sorted. JavaDoc of SortedTable
When executing a report in MSCRM 2011, you have two options for the data sources : either SQL or Fetch.
In SSRS execution logs, the user who ran the report is always the service account.
When using fetch, in the report execution log, there is a parameter CRM_FullName containing the full name of the user who ran the report.
When using SQL source, there is no CRM_FullName parameter. How can I know who ran the report? There must be a way to know, since the Filtered views know who I am.
There is actually no way to find this information. When you create a report for MSCRM, you use a connector called "MSCRM Data Connector". This can be seen in the AdditionnalInfo column of the ExecutionLogs3 view on the SSRS instance. When using this connector and trying to show a report, you will get prompted for username and password. That's where things get interesting.
The report is not actually expecting a username/password! In fact, it expects to receive the systemuserid (guid) as username and the organizationid (guid) as password. It then search in the MSCRM_CONFIG database for the organization database settings. Then, it goes into the organization database and simply do a set context_info SYSTEMUSERID. Finally, the filteredviews are calling a function named '[dbo].[fn_FindUserGuid]' that retrieves the context_info. That is how the filtered views are properly working, while connected as the service account.
As you might have expected, we can't know the user who ran the report because the username and password prompts in SSRS are never logged anywhere (for security matters, perhaps).
The best option that I have found to log who ran a report is to actually create a stored procedure that will make a select statement on the filtered views (or any tables, as it is) and then log into a separate table the statement, the procedure parameters and the context_info(). Then, in SSRS I call that function instead of going to the filtered views directly.
Answer edited to include the getting the user fullname if sql source is used.
Register a parameter, UserID, with default value as
=User!UserID
Use the following query in your dataset
SELECT DomainName, FullName
FROM SystemUserBase
WHERE (DomainName = #UserID)
Then use
=Fields!FullName.Value
in your report.
In the CRM the user data is stored in the SystemUserBase table, and the DomainName column is the actual Domain\Username stored in User!UserID of the report.
If you prefer using views, use FilteredSystemUser view instead of SystemUserBase table.
For fetchxml try the following:
The operator operator='eq-userid' means equal to the current user.
<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='true'>
<entity name='team'>
<attribute name='name' />
<attribute name='businessunitid' />
<attribute name='teamid' />
<order attribute='name' descending='false' />
<link-entity name='teammembership' from='teamid' to='teamid' visible='false' intersect='true'>
<link-entity name='systemuser' from='systemuserid' to='systemuserid' alias='user'>
<attribute name='fullname' />
<attribute name='systemuserid'/>
<filter type='and'>
<condition attribute='systemuserid' operator='eq-userid' />
</filter>
</link-entity>
</link-entity>
</entity>
</fetch>
Then in your report you can use the following code in an expression to get the users fullname
=First(Fields!user_fullname.Value, "GetUserData")
where the dataset is called GetUserData
Will the user login name suffice? i.e. can you just use something like
="Generated by " & User!UserID ?