Exception when referencing SSAS Tabular model in C# - c#

I am attempting to automate partition refreshes in Azure Analysis Services via C#. I have installed and referenced the latest 'Microsoft.AnalysisServices. ..' assemblies found here:
https://learn.microsoft.com/en-us/azure/analysis-services/analysis-services-data-providers.
I then have the following code:
using System;
using Microsoft.AnalysisServices.Tabular;
public void Run()
{
Server asSrv = new Server();
try
{
asSrv.Connect(ASConnectionString);
Database db = asSrv.Databases.FindByName("HospoIQTabular");
Model m = db.Model;
// only refresh 2017 partitions
m.Tables["Sales"].Partitions["Sales - Post 2017"].RequestRefresh(RefreshType.Full);
m.Tables["Payments"].Partitions["Payments - Post 2017"].RequestRefresh(RefreshType.Full);
db.Model.SaveChanges(); // commit which will execute the refresh
}
catch (Exception e)
{
OnEventLog(e.Message);
}
finally
{
asSrv.Disconnect();
asSrv = null;
}
}
Connect to the server and database itself works fine. However, attempting to reference 'db.Model' throws the following exception:
The value '2' is unexpected for type 'DataSourceType'.
I've looked but can't find any help anywhere on this. Any thoughts??

For me, the path that worked was C:\Program Files (x86)\Microsoft SQL Server\140\SDK\Assemblies
but only after reading Andrae comment which sent me on the right direction

The problem is similar with the NuGet package Microsoft.AnalysisServices.Tabular (v13)
Fortunately you can use the NuGet packages listed here: https://learn.microsoft.com/en-us/azure/analysis-services/analysis-services-data-providers.
In Visual Studio NuGet lists this package as Microsoft.AnalysisServices.retail.amd64

Related

The type initializer for 'System.Data.SqlClient.TdsParser' threw an exception error while calling Stored Procedure from Azure function

I have an Azure Event hub with readings from my smart electricity meter. I am trying to use an Azure Function to write the meter readings to an Azure SQL DB. I have created a target table in the Azure SQL DB and a Stored Procedure to parse a JSON and store the contents in the table. I have successfully tested the stored procedure.
When I call it from my Azure Function however I am getting an error: The type initializer for 'System.Data.SqlClient.TdsParser' threw an exception. For testing purposes, I have tried to execute a simple SQL select statement from my Azure Function, but that gives the same error. I am lost at the moment as I have tried many options without any luck. Here is the Azure function code:
#r "Microsoft.Azure.EventHubs"
using System;
using System.Text;
using System.Data;
using Microsoft.Azure.EventHubs;
using System.Data.SqlClient;
using System.Configuration;
using Dapper;
public static async Task Run(string events, ILogger log)
{
var exceptions = new List<Exception>();
try
{
if(String.IsNullOrWhiteSpace(events))
return;
try{
string ConnString = Environment.GetEnvironmentVariable("SQLAZURECONNSTR_azure-db-connection-meterreadevents", EnvironmentVariableTarget.Process);
using(SqlConnection conn = new SqlConnection(ConnString))
{
conn.Execute("dbo.ImportEvents", new { Events = events }, commandType: CommandType.StoredProcedure);
}
} catch (Exception ex) {
log.LogInformation($"C# Event Hub trigger function exception: {ex.Message}");
}
}
catch (Exception e)
{
// We need to keep processing the rest of the batch - capture this exception and continue.
// Also, consider capturing details of the message that failed to process so it can be processed again later.
exceptions.Add(e);
}
// Once processing of the batch is complete if any messages in the batch failed process throw an exception so that there is a record of the failure.
if (exceptions.Count > 1)
throw new AggregateException(exceptions);
if (exceptions.Count == 1)
throw exceptions.Single();
}
The events coming in are in JSON form as follows
{
"current_consumption":450,
"back_low":0.004,
"current_back":0,
"total_high":13466.338,
"gas":8063.749,
"current_rate":"001",
"total_low":12074.859,
"back_high":0.011,
"timestamp":"2020-02-29 22:21:14.087210"
}
The stored procedure is as follows:
CREATE PROCEDURE [dbo].[ImportEvents]
#Events NVARCHAR(MAX)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON
-- Insert statements for procedure here
INSERT INTO dbo.MeterReadEvents
SELECT * FROM OPENJSON(#Events) WITH (timestamp datetime2, current_consumption int, current_rate nchar(3), current_back int, total_low numeric(8, 3), back_high numeric(8, 3), total_high numeric(8, 3), gas numeric(7, 3), back_low numeric(8, 3))
END
I have added a connection string of type SQL AZURE and changed {your password} by the actual password in the string. Any thoughts on how to fix this issue or maybe how to get more logging as the error is very general?.
I managed to fix this exception by re-installing Microsoft.Data.SqlClient.SNI. Then clean and rebuild your project.
I managed to fix the issue by changing the Runtime version to ~2 in the Function App Settings.
Does this mean this is some bug in runtime version ~3 or should there be another way of fixing it in runtime version ~3?
I might be late to the party, in my case the cause of the error was "Target runtime" when publishing, I developed on windows machine but was transferring the file to linux, the solution was to change target runtime to the correct one, initial it was win-x64(merely because I started off by deploying locally), see screenshot below
Try to connect to a local SQL, use SQL profiler, and check what you are sending, and what precisely SQL is trying to do with the command being executed.
It's very hard to replicate your code, because, I obviously do not have your Azure SQL :)
So I would suggest, try to execute each step in the Stored procedure, as direct queries.
See if that works, then try to wrap the statements into store-procedures called back-to-back, and get that to work.
Then combine the commands to a single command, and fiddle with it till you get it to work ;)
Get the most simple query to execute towards the Azure SQL, so you are sure your connection is valid. (Like just a simple select on something)
Because without more information, it is very difficult to assist you.
Pretty silly but I got this after installing the EntityFrameworkCore Nuget package but not EntityFrameworkCore.SqlServer Nuget package. I had the SqlServer version for EntityFramework 6 installed.
I had the same error with a VSTO-application that was installed with a double click in the file explorer. Windows copied not all files to such an automatic location somewhere into ProgramData, so the application was simply not complete!
The solution was to register the VSTO-application manualy in HKEY_CURRENT_USER and pointed the "Manifest" to the complete directory with all the files. (like Microsoft.Data.SqlClient.dll, Microsoft.Data.SqlClient.SNI.x64.dll etc)
Those automatically by Windows chosen installations/directories will give unexpected behaviour. :(
Some ws methods ran fine and other would fail with this same error. I ran ws method that was failing in the browser on the box that the ws was being served from and got a lengthy, and helpful error message. One item was an InnerException that said
<ExceptionMessage>Failed to load C:\sites\TXStockChecker.xxxxxx.com\bin\x64\SNI.dll</ExceptionMessage>
I noticed that that file was right were it was expected in my development environment so I copied it to the matching directory on the prod ws and now all the methods run as expected.

Cannot get ValidStates of WindowsInstaller features

I've encountered a problem when I try to retrieve the valid states of all features within an MSI package using the Microsoft.Deployment.WindowsInstaller.Installer class.
I want to copy the ValidStates property of each FeatureInfo within a Session. However when doing so I get a "Handle is in an invalid state." exception.
If I print each of these values out using Console.WriteLine() or step through the code in Visual Studio there is no exception.
I am at a loss as to what is preventing me from doing this.
Thanks in advance!
My Code:
var featureDictionary = new Dictionary<string, string[]>();
if (string.IsNullOrWhiteSpace(mPath))
return featureDictionary;
try
{
Installer.SetInternalUI(InstallUIOptions.Silent);
using (var session = Installer.OpenPackage(mPath, true))
{
foreach (var feature in session.Features)
{
try
{
var states = feature.ValidStates.Select((state) => state.ToString());
featureDictionary.Add(feature.Name, states.ToArray());
}
catch (InstallerException ex)
{
Debug.WriteLine(ex.Message);
}
}
}
}
catch (InstallerException) { }
return featureDictionary;
The basic problem appears to be that you are opening the MSI as a file. Since you haven't posted its declaration, or how it is set, I'm assuming that mpath means it's a path to the file. Your OpenPackage method parameters seem to indicate this too. You're getting that error because you are trying to open the MSI file as a file during the actual install, and failing.
The way to get hold of the database for the running install is to use Session.Database.
You can't open the running MSI as a file during the install perhaps for the same reason you can't run an MSI file that you have open with Orca, a simple file sharing violation. When you step through with Visual Studio you're simply accessing the static file and getting default values and the file isn't being used for an install. The other issue is that there can only be one Session object per process (as the OpenPackage docs say) and you are attempting to get a second one while there is already a Session object associated with the handle of the install.
As a custom action it needs to be sequenced after CostFinalize.
Windows Installer conditional expressions such as !feature-state will tell you what state the feature is in, because it's usually better to avoid code where Windows Installer will just give you the answer.

Getting an attachment using EWS and C# failing with ServiceMethodException

So i am currently building an application that allows a group of users to view all emails from a certain email address. This all works correctly. The problem I am encountering comes when i am trying to get the attachments.
I am relatively new to this area and used the example from Microsoft found here. Compare this to my code below:
protected internal override Stream GetAttachmentStreamFinal(MailAttachmentDetails attachment)
{
var response = m_service.GetAttachments(new[] { attachment.Id }, BodyType.Text, Enumerable.Empty<PropertyDefinitionBase>());
if (response.OverallResult != ServiceResult.Success)
{
if (response.Count > 0)
{
var ex = new MailException(response[0].ErrorMessage);
ex.Data.Add(response[0].ErrorCode, response[0].ErrorMessage);
foreach (var ed in response[0].ErrorDetails)
{
ex.Data.Add(ed.Key, ed.Value);
}
throw ex;
}
throw new MailException("Error occurred while fetching the attachment from the mail service.");
}
foreach (var attachmentResponse in response)
{
if (attachmentResponse.Attachment is FileAttachment)
{
var fa = attachmentResponse.Attachment as FileAttachment;
var cs = new MemoryStream(fa.Content);
fa.Load(cs);
cs.Seek(0, SeekOrigin.Begin);
return cs;
}
}
return null;
}
As you can see both sets of code are very similar. However when I step through and get to the attachmentResponse.Attachment is FileAttachment line I get this error thrown
Attempt by method 'Mail.ExchangeEmailService.GetAttachmentStreamFinal(Mail.MailAttachmentDetails)' to access method 'Microsoft.Exchange.WebServices.Data.GetAttachmentResponse.get_Attachment()' failed.
Everything is being passed in correctly and the response returns as success.
I have noticed when stepping through my code that Attachment shows as a non-public member. But as this is encapsulated in Microsofts class im unsure as to why that is the case or what i can do?
I just want to expand on #Jason Johnstons answer.
For some reason the version of EWS in NuGet is not correct. It throws the error that you are experiencing.
A workaround is to remove the reference to the NuGet package via
Uninstall-Package Microsoft.Exchange.WebServices
Then download and run the MSI file here
https://www.microsoft.com/en-us/download/details.aspx?id=42951
This will install the DLLs you require to the default location of
[ C:\Program Files\Microsoft\Exchange\Web Services\2.2 ]
Then simply copied they into your lib directory (or such) and created references to the DLLs directly instead.
Credit: http://www.resolvinghere.com/sm/microsoftexchangewebservicesdatagetattachmentresponsegetattachment-failed.shtml
As the other answers already mentioned, the nuget package from Microsoft is not up to date. I also had the same problem as the OP.
First I solved it by following the answer of Daniel - SDS Group. But then I found the nuget package Exchange.WebServices.Managed.Api from marklamley. It is the current version 2.2.1.1 of the ews-managed-api GitHub project.
Make sure you have the latest version of the Microsoft.Exchange.WebServices.dll. Older versions didn't return the actual attachment data when calling that particular overload of the GetAttachments method.

Display a ConnectionString dialog

I'm trying to create a program in C# that should be able to create, backup and restore a SQL Server database.
For this, the user needs to be able to setup a connection string to the desired SQL Server (and database).
I would like to use the same dialog as for example Visual Studio for creating the connection string.
Is this possible?
The data connection dialog component linked to in this answer is no longer available for download.
However, a (apparently somewhat altered) DataConnectionDialog component has since become available on NuGet.
Installation:
Add the component to your Visual Studio project via the NuGet package manager console:
Install-Package DataConnectionDialog
Usage example:
// using Microsoft.Data.ConnectionUI;
// using System.Windows.Forms;
bool TryGetDataConnectionStringFromUser(out string outConnectionString)
{
using (var dialog = new DataConnectionDialog())
{
// If you want the user to select from any of the available data sources, do this:
DataSource.AddStandardDataSources(dialog);
// OR, if you want only certain data sources to be available
// (e.g. only SQL Server), do something like this instead:
dialog.DataSources.Add(DataSource.SqlDataSource);
dialog.DataSources.Add(DataSource.SqlFileDataSource);
…
// The way how you show the dialog is somewhat unorthodox; `dialog.ShowDialog()`
// would throw a `NotSupportedException`. Do it this way instead:
DialogResult userChoice = DataConnectionDialog.Show(dialog);
// Return the resulting connection string if a connection was selected:
if (userChoice == DialogResult.OK)
{
outConnectionString = dialog.ConnectionString;
return true;
}
else
{
outConnectionString = null;
return false;
}
}
}
Note: The dialog component referred to below is no longer available for download. Unless you have retrieved it in the past, you will probably not get this answer's sample code to work.
Alternative: There is now a different DataConnectionDialog available on
NuGet. See this answer for details.
"Data Connection Dialog" on MSDN Archive Gallery (broken as of 1 Sept. 2015)
The data connection dialog is a database tool component released with Visual Studio. It allows users to build connection strings and to connect to specific data sources. try this..
C# Sample:
static void Main(string[] args)
{
DataConnectionDialog dcd = new DataConnectionDialog();
DataConnectionConfiguration dcs = new DataConnectionConfiguration(null);
dcs.LoadConfiguration(dcd);
if (DataConnectionDialog.Show(dcd) == DialogResult.OK)
{
// load tables
using (SqlConnection connection = new SqlConnection(dcd.ConnectionString))
{
connection.Open();
SqlCommand cmd = new SqlCommand("SELECT * FROM sys.Tables", connection);
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
Console.WriteLine(reader.HasRows);
}
}
}
}
dcs.SaveConfiguration(dcd);
}
Here source code also available. we can integrate and redistribute the source code with our application according to license.
Yes and no.
Yes, it is technically possible, but I urge you not to; that dialog is part of Visual Studio and is lot listed in "redist". My interpretation is that you are not free to redistribute this dll.
I think all the other answers here are out-of-date, but I found a current solution at code.msdn.microsoft.com:
Using Microsoft Visual Studio Connection Dialog at runtime
In Visual Studio when a developer wants to create strong typed classes for database tables either for the conventional TableAdapter or Entity Framework there is a place in the process where a dialog is displayed as shown below. I will show you how to do this at runtime and a bit more.
The download is a solution that builds the following dlls:
Microsoft.Data.ConnectionUI.Dialog.dll
Microsoft.Data.ConnectionUI.dll
Microsoft.Data.DataConnectionConfiguration.dll
The solution also contains a sample application showing how to use them.
Worked a treat for me and it is super easy.
You can use UDL file.
Configuring Data Controls to Use Universal Data Link (.udl) Files
You can use SQLConnectionStringUI Nuget package.
I created some code that will do this. The code is in GitHub and you can learn about it here: https://csharpdeveloper.wordpress.com/2020/05/07/a-c-net-dialog-for-connecting-to-sql-server/
Lin
Create your own form similar to Server Explorer Connection Setting window, and implement it. You cannot use that form meant for VS

ExchangeServiceBinding namespace error

Summary: application will not accept the ExchangeServiceBinding command.
Details:
I am trying to loop through a very large mailbox, so I am using an index to break the inbox into 200 email chunks. The only example I could find (shown below) keeps returning
the type or namespace name “ExchangeServiceBinding” could not be found (are you missing a using directive or an assembly reference? )
Which I find strange, because I am using it using Microsoft.Exchange.WebServices;. Any ideas or help is greatly appreciated. I am running Windows 7 and Visual Studio 2010 and trying to access Exchange 2007 mailboxes.
Things I've tried:
searching Google
searching Stack Overflow
searching MSDN
slamming my head on my desk
trial and error
Code:
// Create binding variable to be used for GetItemsFromInbox().
// Set up the binding with credentials and URL.
ExchangeServiceBinding binding = new ExchangeServiceBinding();
binding.Credentials = new NetworkCredential(dUser, dPassword, dDomain);
binding.Url = new Uri("https://" + ExchangeServerName + "/EWS/Exchange.asmx");
// Set up the binding for Exchange impersonation.
binding.ExchangeImpersonation = new ExchangeImpersonationType();
binding.ExchangeImpersonation.ConnectingSID = new ConnectingSIDType();
binding.ExchangeImpersonation.ConnectingSID.PrimarySmtpAddress = "mailboxnamehere”;
// Call GetItemsFromInbox()
int index = 0;
bool looping = true;
while (looping)
{
List<ItemType> items = GetItemsFromInbox(binding, index, 200, index);
if (items == null || items.count == 0)
{
looping = false;
break;
}
// Do your work here
}
Instead of the Exchange Web Services, use the Exchange Managed API.
SDK: http://msdn.microsoft.com/en-us/library/dd633710(v=exchg.80).aspx
Download: http://www.microsoft.com/download/en/details.aspx?id=13480
It's much easier to use than the WebServices.
I found my error. This methodology only works for Exchange 2010. Since I am running Exchange 2007 I will have to figure out a completely different way to make this work.
Thank you everyone for you help, I really appreciate it.
You should add a WebReference to your solution to the exchange WebService.
https://exchaneServerName/EWS/Exchange.asmx
ExchangeServiceBinding is contained into the ews.dll. According to your error, you didn't add a reference to this DLL file.
More information about Generating Exchange Web Services Proxy Classes:
So now you have a code file with the autogenerated proxies. Next, you compile your code file into an assembly for use in your Exchange Web Services projects. The C# compiler is available with the Visual Studio 2005 Command Prompt. Assuming that you named your code file EWS.cs, you can run the following command at the command prompt to compile your code into an assembly:
csc /target:library /out:EWS.dll EWS.cs
Notice that EWS.dll is the name of the compiled assembly. This is how EWS.dll is created.

Categories

Resources