SSDT: How to configure SchemaCompare Object settings in code - database-schema

How to edit the SchemaCompare Settings in the SchemaComparison object?
$SchemaComparison = [SchemaComparison]::new( $SourceEndPoint, $TargetEndPoint )
$SchemaComparison.Options = $DeployOptions
I am particularly looking to Remove Database options, but the SchemaCompare settings do not appear to be accessible by code:
$SchemaComparison.Options.ExcludeDatabaseOptions #(not known property of the Options object)
$SchemaComparison.SettingsService #(not a known property)
How can I do in code what I can EASILY do from the SSDT compare UI?

I found the answer. There is an excludedObjects property hiding in the options object. It's an array of ObjectType enums:
$SchemaComparison.Options.ExcludeObjectTypes += [ObjectType]::Aggregates
$SchemaComparison.Options.ExcludeObjectTypes += [ObjectType]::ApplicationRoles
$SchemaComparison.Options.ExcludeObjectTypes += [ObjectType]::Assemblies
You can exclude any you want. The MSDN includes the list here:
https://msdn.microsoft.com/en-us/library/microsoft.sqlserver.dac.objecttype.aspx

Related

FileManager: Attribute for when a file was last opened

I need a way of checking when a file was last opened. I tried by creating a custom FileAttributeKey and setting that to the current Date, but when I go to open the file again the attribute does not exist:
private let key = FileAttributeKey(rawValue: "lastOpenedAt")
do {
try FileManager.default.setAttributes(
[key: Date()],
ofItemAtPath: videoNameDirectoryPath
)
} catch {
Log.error(error.localizedDescription)
}
So now I am resorting to using the modification date key to say when I last opened the file, it is not ideal so I am wondering if there is a better way to do this
setAttributes doesn't support custom attributes, you can only use the documented ones.
To set your own attributes, you may use xattr as described in this question:
Write extend file attributes swift example
If you're lucky, you may use kMDItemLastUsedDate from Spotlight aka MDItem as described in the documentation archive of File Metadata Attributes.

Explicitly ignoring source properties in MapStruct

We want to be able to set an unmappedSourcePolicy to ReportingPolicy.ERROR, so that by default missing sources fail loudly. However, there will be times when the source object model contains something not relevant to the target. So we are looking to be able to do something like:
#Mapping(source = "fieldToIgnore", ignore = true)
Like can be done for targets. If I try the above, I get errors because target is required in a mapping.
Source properties can be ignored by using BeanMapping#ignoreUnmappedSourceProperties. In your case you can do
#BeanMapping(ignoreUnmappedSourceProperties = { "fieldToIgnore" })

Disable logging on FileConfigurationSourceChanged - LogEnabledFilter

I want Administrators to enable/disable logging at runtime by changing the enabled property of the LogEnabledFilter in the config.
There are several threads on SO that explain workarounds, but I want it this way.
I tried to change the Logging Enabled Filter like this:
private static void FileConfigurationSourceChanged(object sender, ConfigurationSourceChangedEventArgs e)
{
var fcs = sender as FileConfigurationSource;
System.Diagnostics.Debug.WriteLine("----------- FileConfigurationSourceChanged called --------");
LoggingSettings currentLogSettings = e.ConfigurationSource.GetSection("loggingConfiguration") as LoggingSettings;
var fdtl = currentLogSettings.TraceListeners.Where(tld => tld is FormattedDatabaseTraceListenerData).FirstOrDefault();
var currentLogFileFilter = currentLogSettings.LogFilters.Where(lfd => { return lfd.Name == "Logging Enabled Filter"; }).FirstOrDefault();
var filterNewValue = (bool)currentLogFileFilter.ElementInformation.Properties["enabled"].Value;
var runtimeFilter = Logger.Writer.GetFilter<LogEnabledFilter>("Logging Enabled Filter");
runtimeFilter.Enabled = filterNewValue;
var test = Logger.Writer.IsLoggingEnabled();
}
But test reveals always the initially loaded config value, it does not change.
I thought, that when changing the value in the config the changes will be propagated automatically to the runtime configuration. But this isn't the case!
Setting it programmatically as shown in the code above, doesn't work either.
It's time to rebuild Enterprise Library or shut it down.
You are right that the code you posted does not work. That code is using a config file (FileConfigurationSource) as the method to configure Enterprise Library.
Let's dig a bit deeper and see if programmatic configuration will work.
We will use the Fluent API since it is the preferred method for programmatic configuration:
var builder = new ConfigurationSourceBuilder();
builder.ConfigureLogging()
.WithOptions
.DoNotRevertImpersonation()
.FilterEnableOrDisable("EnableOrDisable").Enable()
.LogToCategoryNamed("General")
.WithOptions.SetAsDefaultCategory()
.SendTo.FlatFile("FlatFile")
.ToFile(#"fluent.log");
var configSource = new DictionaryConfigurationSource();
builder.UpdateConfigurationWithReplace(configSource);
var defaultWriter = new LogWriterFactory(configSource).Create();
defaultWriter.Write("Test1", "General");
var filter = defaultWriter.GetFilter<LogEnabledFilter>();
filter.Enabled = false;
defaultWriter.Write("Test2", "General");
If you try this code the filter will not be updated -- so another failure.
Let's try to use the "old school" programmatic configuration by using the classes directly:
var flatFileTraceListener = new FlatFileTraceListener(
#"program.log",
"----------------------------------------",
"----------------------------------------"
);
LogEnabledFilter enabledFilter = new LogEnabledFilter("Logging Enabled Filter", true);
// Build Configuration
var config = new LoggingConfiguration();
config.AddLogSource("General", SourceLevels.All, true)
.AddTraceListener(flatFileTraceListener);
config.Filters.Add(enabledFilter);
LogWriter defaultWriter = new LogWriter(config);
defaultWriter.Write("Test1", "General");
var filter = defaultWriter.GetFilter<LogEnabledFilter>();
filter.Enabled = false;
defaultWriter.Write("Test2", "General");
Success! The second ("Test2") message was not logged.
So, what is going on here? If we instantiate the filter ourselves and add it to the configuration it works but when relying on the Enterprise Library configuration the filter value is not updated.
This leads to a hypothesis: when using Enterprise Library configuration new filter instances are being returned each time which is why changing the value has no effect on the internal instance being used by Enterprise Library.
If we dig into the Enterprise Library code we (eventually) hit on LoggingSettings class and the BuildLogWriter method. This is used to create the LogWriter. Here's where the filters are created:
var filters = this.LogFilters.Select(tfd => tfd.BuildFilter());
So this line is using the configured LogFilterData and calling the BuildFilter method to instantiate the applicable filter. In this case the BuildFilter method of the configuration class LogEnabledFilterData BuildFilter method returns an instance of the LogEnabledFilter:
return new LogEnabledFilter(this.Name, this.Enabled);
The issue with this code is that this.LogFilters.Select returns a lazy evaluated enumeration that creates LogFilters and this enumeration is passed into the LogWriter to be used for all filter manipulation. Every time the filters are referenced the enumeration is evaluated and a new Filter instance is created! This confirms the original hypothesis.
To make it explicit: every time LogWriter.Write() is called a new LogEnabledFilter is created based on the original configuration. When the filters are queried by calling GetFilter() a new LogEnabledFilter is created based on the original configuration. Any changes to the object returned by GetFilter() have no affect on the internal configuration since it's a new object instance and, anyway, internally Enterprise Library will create another new instance on the next Write() call anyway.
Firstly, this is just plain wrong but it is also inefficient to create new objects on every call to Write() which could be invoked many times..
An easy fix for this issue is to evaluate the LogFilters enumeration by calling ToList():
var filters = this.LogFilters.Select(tfd => tfd.BuildFilter()).ToList();
This evaluates the enumeration only once ensuring that only one filter instance is created. Then the GetFilter() and update filter value approach posted in the question will work.
Update:
Randy Levy provided a fix in his answer above.
Implement the fix and recompile the enterprise library.
Here is the answer from Randy Levy:
Yes, you can disable logging by setting the LogEnabledFiter. The main
way to do this would be to manually edit the configuration file --
this is the main intention of that functionality (developers guide
references administrators tweaking this setting). Other similar
approaches to setting the filter are to programmatically modify the
original file-based configuration (which is essentially a
reconfiguration of the block), or reconfigure the block
programmatically (e.g. using the fluent interface). None of the
programmatic approaches are what I would call simple – Randy Levy 39
mins ago
If you try to get the filter and disable it I don't think it has any
affect without a reconfiguration. So the following code still ends up
logging: var enabledFilter = logWriter.GetFilter();
enabledFilter.Enabled = false; logWriter.Write("TEST"); One non-EntLib
approach would just to manage the enable/disable yourself with a bool
property and a helper class. But I think the priority approach is a
pretty straight forward alternative.
Conclusion:
In your custom Logger class implement a IsLoggenabled property and change/check this one at runtime.
This won't work:
var runtimeFilter = Logger.Writer.GetFilter<LogEnabledFilter>("Logging Enabled Filter");
runtimeFilter.Enabled = false/true;

Typesafe/Hocon config: variable substitution: reference path

We have a project with huge configuration files built using hocon configs.
There is an intention to use variables to create template_section and set up some values in the template based on some options.
The problem is that while using variables in this config, I have to refer to the absolute path all the time.
Is it possible somehow to use the canonical name (if properties located on the same level)?
Example:
foo {
bar = 4
baz = ${foo.bar} // work perfect
baz = ${[this].bar} // can I do smth like that? Any ideas.
}
A more real-life example. What I'm actually looking for is general OOP abilities in building hocon configs.
I have some parent configuration template_config with important_option inside that really depends on implementation:
custom_config1 or custom_config2, I currently have to implement important_option in both child configurations because with absolute paths, I have to refer to custom config sections names.
custom_config1: $template_config {
child_option = child_value1
}
custom_config2: $template_config {
child_option = child_value2
}
template_config {
important_option = ${child_option} // NOT POSSIBLE
child_option = not_implemented
}
Sadly, your hypothetical baz = ${[this].bar} path self-reference is not a thing that is supported by HOCON (as of 2022)

How to copy properties from source node to destination node in cq

I want to get Some Property from Source Node Using getProperties() and setProperty in another Destination Node. How can i check that property is protected or not.As if i copy all the property in destination it gives me ConstraintViolationException
You'd need to get the definition of the property:
PropertyDefinition propDefinition = node.getProperty("/yourprop").getDefinition();
on the definition you can call isProtected():
Boolean isPropertyProtected = propDefinition.isProtected();
or just inline it:
node.getProperty("/yourprop").getDefinition().isProtected();
for further reading I suggest:
http://www.day.com/specs/jcr/2.0/16_Access_Control_Management.html;
Chapter 16.3.12 Interaction with Protected Properties
And the JCR documentation on node types:
http://jackrabbit.apache.org/jcr/node-types.html
This is probably because you are trying to copy all properties which includes cq:primaryType as well. If you see in crx, these basic properties are not editable.
For copy you can take a specific property and set a specific property, instead of copying and pasting all the properties.