I have a rich text field in my winform app where I can write sql script
and need to check whether any issue is there in written script or not.
Is there any way to do the same task just before it's execution using c#?
Any type of suggestion is highly appreciated.
Thanks,
Anil
If you are only trying to validate the syntax (and not the existence of the database objects), you may take a look at the TSqlParser Class.
You will need to add the following references to your project:
Microsoft.Data.Schema.ScriptDom
Microsoft.Data.Schema.ScriptDom.Sql
A simple way to do that is to edit your .csproj file and add the following two entries along with the existing ones and reload the project:
<ItemGroup>
<Reference Include="Microsoft.Data.Schema.ScriptDom.Sql" />
<Reference Include="Microsoft.Data.Schema.ScriptDom" />
<!-- other Reference tags -->
</ItemGroup>
Some sample usage:
private void btnParse_Click(object sender, EventArgs e)
{
var parser = new TSql100Parser(true);
IList<ParseError> errors;
var result = parser.Parse(new StringReader(richTextBox1.Text), out errors);
// TODO: check the errors
}
Related
Created a new "WPF Application" .NET 6.0 project
There creating classical Application Settings was easy in project->properties->Settings->"Create or open application settings"
Observed: the project gets a new folder "Properties" which has a yellow Folder icon with an additional black wrench symbol, okay
It contains a new item Settings.settings that can get edited via classical Settings Designer looking like it used to look in .Net 4.8, and a new App.config XML file is getting created automatically in the project's root folder which also looks like it used to in .Net 4.8, okay
Now the same procedure can apparently only be done manually in
a new "Class Library" project being added in the same solution where I would want to use that Properties.Settings / app.config feature pack for storing a DB connection string configurably:
the new sub-project does not seem to have a "Settings" option in the project Properties dialog (as opposed to a .Net4.x would have had)
the new Properties folder and new Settings file can be created successfully there too manually as described in Equivalent to UserSettings / ApplicationSettings in WPF .NET 5, .NET 6 or .Net Core
but doing a "Rebuild solution" gives an
Error CS1069 The type name 'ApplicationSettingsBase' could not be found in the namespace 'System.Configuration'. This type has been forwarded to assembly 'System.Configuration.ConfigurationManager, Version=0.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' Consider adding a reference to that assembly. ClassLibrary1 C:\Users\Stefan\source\repos\WpfCorePropertiesSettings\ClassLibrary1\Properties\Settings.Designer.cs 16 Active
as a next step adding NuGet package "System.Configuration.Abstractions" to the Class Library project cures the symptom, "rebuild solution" makes the error disappear.
TLDNR, actual question: is that sequence an acceptable solution or a kludge to avoid?
To me the NuGet package description does not sound as if the package was made for that purpose, and I have not heard the maintainers' names before (which might or might not matter?)
https://github.com/davidwhitney/System.Configuration.Abstractions
TIA
PS:
Maybe I don't understand something...
Why create "Equivalent to UserSettings"?
My configuration is Win10+VS2022. I am creating a WPF .Net6 project. I go to the "Project Properties" menu. In the menu of the project properties tab (column on the left) there is an item Options. When selected, if the settings have not yet been created, there will be a small comment and a link to "Open or create application settings".
Unfortunately, I have Russian localization, so the screenshots are with Russian names.
Addition
But an additional "Class Library" sub-project does not seem to have that Project Properties option in my En/US localization. Does it in yours?
These are the APP settings.
Therefore, they do not make much sense in the library.
But if you need to, you can just copy the class to the library and then set up the links you need.
To do this, type in the application code the line Properties.Settings.Default.Save();. Move the cursor to Settings and press the F12 key.
You will be taken to the source code for the Settings class declaration. This code is generated by a code generator.
After moving to, copy all the source code into a class in another project. After the migration, you may need to add references in the project, fix the namespace and add usings.
As for the parameters in the «Class Library» project, it probably depends on what type this library is.
I have such settings in the «Class Library for WPF».
But in Libraries for Standard - no.
In the meantime I'm happy with a custom "AppSettings.json" approach.
After removing the previously described "classical app.config" approach, and after adding two NuGet packages:
<PackageReference Include="Microsoft.Extensions.Configuration" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
... I created a custom Json file on "Class Library" (sub)project level in Visual Studio manually, and set its CopyToOutputDirectory property
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
And added an 'IConfigurationBuilder` part:
using Microsoft.Extensions.Configuration;
namespace Xyz.Data
{
internal class AppSettingsConfig
{
public AppSettingsConfig()
{
IConfigurationBuilder builder = new ConfigurationBuilder();
_ = builder.AddJsonFile(Path.Combine(Directory.GetCurrentDirectory(), "AppSettings.Movies3Data.json"));
var root = builder.Build();
AttachedDb = root.GetConnectionString("AttachedDb")!;
}
public string AttachedDb { get; init; }
}
}
And then made it a "Jon Skeet singleton"
/// <summary>
/// Singleton as described by Jon Skeet
/// </summary>
/// https://csharpindepth.com/Articles/Singleton
internal sealed class AppSettingsConfigSingleton
{
private static readonly Logger log = LogManager.GetCurrentClassLogger();
private AppSettingsConfigSingleton()
{
log.Trace($"{nameof(AppSettingsConfigSingleton)} ctor is running");
IConfigurationBuilder builder = new ConfigurationBuilder();
_ = builder.AddJsonFile(Path.Combine(Directory.GetCurrentDirectory(), "AppSettings.Movies3Data.json"));
var root = builder.Build();
AttachedDb = root.GetConnectionString("AttachedDb")!;
}
static AppSettingsConfigSingleton() { }
public string? AttachedDb { get; init; }
public static AppSettingsConfigSingleton Instance { get { return Nested.instance; } }
private class Nested
{
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static Nested()
{
}
internal static readonly AppSettingsConfigSingleton instance = new();
}
}
And it "works well" by also reading JSON content just having been modified by admins at run-time. (Which would be the Entity Framework Core "localdb" location for the unit-of-work pattern in a multi-UI solution). Thanks again to you too, #EldHasp
I use SpecFlow with Coded UI to create some automated functional tests for a WPF application. Test case execution is performed using MsTest and Visual Studio Premium 2012.
I have a lot of test cases. If I execute them one by one everything is OK. If I put them all in an ordered test I receive the following error:
Microsoft.VisualStudio.TestTools.UITest.Extension.UITestControlNotAvailableException: The following element is no longer available: Name [], ControlType [Custom], AutomationId [reags:LoadView_1], RuntimeId [7,1620,64780193] ---> System.Windows.Automation.ElementNotAvailableException: The following element is no longer available: Name [], ControlType [Window], AutomationId [UnitializedCB3702D1-14B6-4001-8BC7-CD4C22C18BE1], RuntimeId [42,1770052]
at Microsoft.VisualStudio.TestTools.UITest.Extension.Uia.UiaUtility.MapAndThrowException(SystemException e, IUITechnologyElement element)
at Microsoft.VisualStudio.TestTools.UITest.Extension.Uia.UiaElement.get_AutomationId()
at Microsoft.VisualStudio.TestTools.UITest.Extension.Uia.UiaElement.HasValidAutomationId()
at Microsoft.VisualStudio.TestTools.UITest.Extension.Uia.UiaElement.get_FriendlyName()
at Microsoft.VisualStudio.TestTools.UITest.Common.UIMap.UIMapUtil.FillPropertyFromUIElement(UIObject obj, IUITechnologyElement element)
at Microsoft.VisualStudio.TestTools.UITest.Common.UIMap.UIMapUtil.FillPropertyOfTopLevelElementFromUIElement(UIObject obj, IUITechnologyElement element)
at Microsoft.VisualStudio.TestTools.UITest.Common.UIMap.UIMapUtil.FillTopLevelElementFromUIElement(IUITechnologyElement element, TopLevelElement obj, Boolean stripBrowserWindowTitleSuffix)
at Microsoft.VisualStudio.TestTools.UITest.Common.UIMap.UIMapUtil.GetCompleteQueryId(UITechnologyElement pluginNode)
at Microsoft.VisualStudio.TestTools.UITesting.UITestControl.GetQueryIdForCaching()
at Microsoft.VisualStudio.TestTools.UITesting.UITestControl.<>c__DisplayClass6.<CacheQueryId>b__5()
at Microsoft.VisualStudio.TestTools.UITesting.CodedUITestMethodInvoker.InvokeMethod[T](Func`1 function, UITestControl control, Boolean firePlaybackErrorEvent, Boolean logAsAction)
at Microsoft.VisualStudio.TestTools.UITesting.UITestControl.CacheQueryId(String queryId)
at Microsoft.VisualStudio.TestTools.UITesting.UITestControl..ctor(IUITechnologyElement element, UITestControl searchContainer, String queryIdForRefetch)
at Microsoft.VisualStudio.TestTools.UITesting.TechnologyElementPropertyProvider.GetPropertyValue(UITestControl uiControl, String propertyName)
at Microsoft.VisualStudio.TestTools.UITesting.UITestPropertyProvider.TryGetPropertyFromTechnologyElement(UITestControl uiControl, String propertyName, Object& value)
at Microsoft.VisualStudio.TestTools.UITesting.PropertyProviderBase.GetPropertyValue(UITestControl uiControl, String propertyName)
at Microsoft.VisualStudio.TestTools.UITesting.UITestPropertyProvider.GetPropertyValueWrapper(UITestControl uiControl, String propertyName)
at Microsoft.VisualStudio.TestTools.UITesting.UITestControl.GetPropertyValuePrivate(String propertyName)
The first couple of errors were fixed using this hint, but I have some auto-generated steps and in order to re-search the controls I have to move the code and... a lot of unnecessary and annoying work.
Could you suggest some another solution to fix this? Is there some trick with the ordered tests? Or some nice clean-up methods for problems like this?
Thanks!
Here's what I did with a recent project.
First I created some CodedUI test methods as if SpecFlow didn't exist so I could keep those layers separate. Then I created step definition classes in C# that delegate to the coded UI test methods I created.
In a before scenario hook I created my UIMap instances (the classes generated by the CodedUI test generator) so each scenario had a fresh instance of my UIMap classes. You need this because object references in these classes are cached. Each new screen in your app is a whole new object tree that CodedUI must traverse.
Many times my step definitions just dive right into the CodedUI API to create custom searches, and I used the auto generated methods in my UIMap classes as a point of reference.
A little elaboration on how I set up my test project.
About My Test Project
I created a new "Test" project in Visual Studio 2010, which references the following libraries:
Microsoft (probably comes with default Test project template)
Microsoft.VisualStudio.QualityTools.CodedUITestFramework
Microsoft.VisualStudio.QualityTools.UnitTestFramework
Microsoft.VisualStudio.TestTools.UITest.Common
Microsoft.VisualStudio.TestTools.UITest.Extension
Microsoft.VisualStudio.TestTools.UITesting
UIAutomationTypes
NuGet Packages
AutoMapper
AutoMapper.Net4
SpecFlow.Assist.Dynamic
TechTalk.SpecFlow
Test Project Structure
This was my first stab at CodedUI Tests. I came from a Ruby on Rails background, and did a fair amount of reading online about implementing CodedUI Tests and SpecFlow tests. It's not a perfect setup, but it seems to be pretty maintainable for us.
Tests (Test project)
Features/
Bar.feature
Foo.feature
Regression/
Screen1/
TestsA.feature
TestsB.feature
StepDefinitions/
CommonHooks.cs
DataAssertionSteps.cs
DataSteps.cs
FormSteps.cs
GeneralSteps.cs
PresentationAssertionSteps.cs
Screen1Steps.cs
Screen2Steps.cs
UI/
FormMaps/
Screen1FormMap.cs
Screen2FormMap.cs
UIMapLoader/
User.cs
UIMap.uitest (created by CodedUI test framework)
Models (C# Class Library Project)
Entities/
Blog.cs
Comment.cs
Post.cs
Repositories/
BlogRepository.cs
CommentRepository.cs
PostRepository.cs
ViewModels/
Screen1ViewModel.cs
Screen2ViewModel.cs
Tests/Features
This folder contains all the SpecFlow feature files implementing the basic business rules, or acceptance tests. Simple screens got their own feature file, whereas screens with more complex business logic were broken into multiple feature files. I tried to keep these features friendly to read for both Business and Developers.
Tests/Regression
Because our Web Application was not architected in a manor allowing unit testing, all of our testing must be done through the UI. The Tests/Regressions folder contains all the SpecFlow feature files for our full regression of the application. This includes the really granular tests, like typing too many characters into form fields, etc. These features weren't really meant as business documenation. They are only meant to prevent us from being woken up at 3 a.m. because of production problems. Why do these problems always happen at 3 a.m.? ...
Tests/StepDefinitions
The Test/StepDefinitions folder contains all the SpecFlow Step Definition files. I broke these files down first into common steps, and then steps pertaining to a particular screen in my application.
CommonHooks.cs -- Created by SpecFlow
[Binding]
public class CommonHooks
{
[BeforeTestRun]
public static void BeforeTestRun()
{
...
}
[BeforeScenario]
public void BeforeScenario()
{
User.General.OpenLauncher();
}
[AfterScenario]
public void AfterScenario()
{
User.General.CloseBrowser();
User.General = null;
}
}
The BeforeScenario and AfterScenario methods are where I create and/or destroy instances of the CodedUI UIMap classes (More on that further down)
DataAssertionSteps.cs -- Step definitions asserting that data shows up, or doesn't show up in the database. These are all Then ... step definitions.
Scenario: Foo
Then a Foo should exist
In DataAssertionSteps.cs:
[Then(#"a Foo should exist")]
public void ThenAFooShouldExist()
{
// query the database for a record
// assert the record exists
}
DataSteps.cs -- Steps to seed the database with data, or remove data. These are all Given ... step definitions used to set up a scenario.
FormSteps.cs -- Step definitions for interacting with forms. These all tend to be When I ... steps
GeneralSteps.cs -- Realy generic step definitions. Things like When I click the "Foo" link go here.
PresentationAssertionSteps.cs -- Generic steps asserting that the UI is behaving properly. Things like Then I should see the text "Foo" go here.
Screen1Steps.cs -- When I needed steps for a particular screen, I created a step definition file for that screen. For example, if I needed steps for the "Blog Post" screen, then I created a file call BlogPostSteps.cs, which contained all those step definitions.
Tests/UI
The Tests/UI folder contains a bunch of custom written C# classes that we used to map label text found in our *.feature files to the names of form controls. You might not need this layer, but we did. This makes it easier to refactor your test project if form control names change, and especially for Web Projects because the HTML form field names change based on the <asp /> containers in our ascx files.
Example class:
namespace Tests.UI.FormMaps.Screen1FormMap
{
public static IDictionary<string, string> Fields = new Dictionary<string, string>()
{
{ "First Name", "UserControlA_PanelB_txtFirstName" },
{ ... },
...
};
}
Example Step:
When I enter "Joe" in the "First Name" textbox in the "Screen 1" form
Example Step Definition:
[When(#"I enter ""(.*)"" in the ""(.*)"" textbox in the ""(.*)"" form")]
public void WhenIEnterInTheTextboxInTheForm(string text, string labelText, string formName)
{
if (formName == "Screen 1")
{
// form control name: Screen1FormMap.Fields[labelText]
}
...
}
The step definition then used the Tests.UI.FormMaps.Screen1FormMap.Fields property to retrieve the form control name based on the label text in the *.feature files.
Tests.UI.FormMaps.Screen1FormMap.Fields["First Name"]
Tests/UI/UIMapLoader/User.cs
The other thing inside this folder is the UI/UIMapLoader/User.cs file. This class is a custom written class providing easy access to all the UIMap classes generated by the CodedUI Test framework.
namespace Tests.UI.UIMapLoader
{
public static class User
{
private static UIMap _general;
public static UIMap General
{
get { return _general ?? (_general = new UIMap()); }
set { _general = value; }
}
}
}
That way the Step Definition classes can easily access the UI maps via:
User.General.SomeCodedUITestRecordedMethod(...);
You saw a reference to this class in the BeforeScenario and AfterScenario methods in the CommonHooks.cs file referenced above.
Models Project
This is just a class lib to encompass the entities and repositories allowing the test project to access the database. Nothing special here except the ViewModels directory. Some of the screens have complex relationships with data in the database, so I created a ViewModel class to allow my SpecFlow step definitions to easily seed the database with data for these screens.
Im having trouble referencing classes in xaml from other assemblies.
In the same solution, i have two projects. One called Controls (to hold user controls) and one called DataBinding (holding converters / validation rules). In a control, im attempting reference a validation rule in xaml:
<Binding.ValidationRules>
<databind:Validators.FileExistsRule />
</Binding.ValidationRules>
My project references the project containing my classes. Ive added this declaration at the top of my Control.xaml:
xmlns:databind="clr-namespace:GuiParts.DataBinding;assembly=DataBinding"
However, when i compile, i get an error:
The tag 'Validators.FileExistsRule' does not exist in XML namespace 'clr-namespace:GuiParts.DataBinding;assembly=DataBinding'.
The class definitely exists, i can call it in the code behind with no problems, but not via xaml. If i move the class to the same project, again, i have no problems. Ive seen other questions on here, and have tried the following:
Cleaning and rebuilding all relevant projects
Ensuring all projects are targeting the same version of .Net (4.0, Full Profile)
Removing the 'assembly' definition from the end of the namespace definition.
None of the above has worked. Any suggestions as to where im going wrong?
EDIT
My FileExists Validator:
namespace GuiParts.DataBinding.Validators
{
/// <summary>
/// Validates that the file with the specified name exists
/// </summary>
public class FileExistsRule : ValidationRule
{
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
ValidationResult res = null;
res = ( ! File.Exists((string)value))
? new ValidationResult(false, "File does not exist")
: new ValidationResult(true, null);
return res;
}
}
}
I can call the following in the code behind without any errors:
new GuiParts.DataBinding.Validators.FileExistsRule();
So ive got my namespaces etc. correct.
Try this:
xmlns:databind="clr-namespace:GuiParts.DataBinding.Validators;assembly=DataBinding"
<Binding.ValidationRules>
<databind:FileExistsRule />
</Binding.ValidationRules>
Is your class in your target assembly public?
Is the field in Validators, public?
Is your namespace GuiParts.DataBinding correct?
While I'm not sure what the issue you're having is, you can alternatively create a friendlier namespace definition for your assembly and CLR namespaces. In fact, I use this technique to group various namespaces into one XML namespace... You do this using the XmlnsPrefixAttribute and the XmlnsDefinitionAttributes.
For example:
[assembly: XmlnsPrefix("http://my.xml.namespace.com/", "databind")]
[assembly: XmlnsDefinition("http://my.xml.namespace.com/",
"GuiParts.DataBinding")]
[assembly: XmlnsDefinition("http://my.xml.namespace.com/",
"GuiParts.DataBinding.Validators")]
Then, when you want to reference the xmlnamespace in your xaml you simply do:
xmlns:databind="http://my.xml.namespace.com/"
Note, I use ReSharper, but I'm sure this also works naturally in Visual Studio. If you don't type in the xmlns import and attempt to use an object in the namespace, then when you go to resolve it it will automatically use the friendlier named namespace with the specified prefix. Also, it's really nice and helps you avoid having a 1:1 relationship between xml namespaces and clr namespaces because you can map multiple clr namespaces into a single xml namespace.
Again, I'm not sure what the issue you're having specifically is, but this will probably fix it and be better than using clr-namespaces and assembly information. Just make sure to come up with something unique so you don't run into xmlns collisions or you'll have to go back to clr/assembly namespacing.
Oh, and one last thing... if you wish to utilize versioning in your xml namespace naming scheme (which you should), don't worry about locking yourself in for backwards compatibility. You can always utilize the XmlnsCompatibleWithAttribute to ensure that code that utilized the old friendly namespace doesn't break if you ever update your external assemblies to map to a newer xml namespace.
For example, if you originally had you're assembly pointing to a 2012 namespace, then switched it to a 2013 namespace because you updated the assembly...
// Previous Assembly version
//[assembly: XmlnsDefinition("http://schemas.xyzcorp.com/wpf/2012",
// "Xyz.Databinding")]
[assembly: XmlnsCompatibleWith("http://schemas.xyzcorp.com/wpf/2012",
"http://schemas.xyzcorp.com/wpf/2013")]
[assembly: XmlnsDefinition("http://schemas.xyzcorp.com/wpf/2013",
"Xyz.Databinding")]
I am trying to make Jeff's testing program, written in Silverlight 2 (http://www.jeff.wilcox.name/2008/03/silverlight2-unit-testing/), work using Silverlight 4 and VS2010 and I get a NullReferenceException at this line:
chatSession.ConnectWithRemoteUser("ScottGu");
Any ideas why? Here's code:
public Page()
{
// commented out because it doesn't exist in the current context
// according to the compiler
// InitializeComponent();
// Retrieve ChatSession instance from XAML resource declaration
chatSession = new ChatSession();
chatSession = (ChatSession)Resources["ChatSessionDS"];
// Connect with Chat Server to chat with "ScottGu"
chatSession.ConnectWithRemoteUser("ScottGu");
}
First, if you had to comment out InitializeComponent(), I Feel bad about your application: InitializeComponent is generated by the VS tools when the XAML file of your page is parsed.
If it doesn't exist, it probably means that the class declared in the xaml file is different from the one in your c# file (different name or different namespace) Otherwise, maybe the XAML file action type in the VS property tab isn't set to "page".
second:
chatSession = new ChatSession();
chatSession = (ChatSession)Resources["ChatSessionDS"];
this looks strange.you create a new ChatSession, then replace it by an object saved in the page resources. Why do you create it firstplace if you put the instance out of scope at the next line?
I have a WpfApplication project (Visual Studio 2008) with an app.config generated from entering 'Name' and 'Value' pairs in the Settings.settings file (and therefore generating 'applicationSettings' elements rather than 'appSettings' elements).
I have added a class1 class library project in the same Visual Studio solution.
** I have added the WpfApplication app.config file to the class1 project using "add existing item and then add as link".** since found out this is unneccassary (i.e. string a = ConfigurationManager.AppSettings.Get("key1"); below works without this)
I want to read the values within app.config from class1 and have explored the following:
string s1 = Settings.Default.appsetting1;
But I do not want to reference the WpfApplication10 project from Class 1 project and so cannot get a reference to the Settings class. So this syntax only works within the WPF project.
string a = ConfigurationManager.AppSettings.Get("key1").ToString();
This does work, but only if I add the following to app.config:
<appSettings>
<add key="key1" value="1"/>
</appSettings>
Are there other ways to achieve what I want which may be better (e.g. offering type safety or being able to read the Settings class properties?
You can do the following thing:
if you need to get value from key="key1" just write this(supposing your app.config is in the correct directory).
string str=System.Configuration.ConfigurationSettings.AppSettings["key1"];