- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我们的 .sqlproj 包含很多这样的语句,用于项目中存在的每个对象:
<Build Include="MySchema\Tables\TableA" />
<Build Include="MySchema\Tables\TableB" />
<Build Include="MySchema\Tables\TableC" />
每当一个对象被添加到项目中时,SSDT 将通过在文件的随机行中添加一条记录来自动更新 sqlproj 文件。当多个开发人员在同一个项目上工作时,这会导致很多合并问题。
我尝试通过向所有模式文件夹添加通配符来修改此文件,因此之前的文件将变为:
<Build Include="MySchema\**" />
但是如果我在同一个模式中创建 TableD,它仍然会为该对象添加一条记录,即使它包含在前面的语句中。所以我的 .sqlproj 看起来像这样:
<Build Include="MySchema\**" />
<Build Include="MySchema\Tables\TableD" />
有什么解决方案可以解决这个问题吗?
最佳答案
合并 SSDT sqlproj 项目文件很痛苦。我们已经创建了 MSBuild 目标文件,它可以在您每次构建项目时简单地对项目文件进行排序。缺点是当 sqlproj 文件被排序时,Visual Studio 认为它被外部修改并且它想要刷新项目。反正跟融合 hell 比起来也没什么大不了的。
因此,在项目文件夹中我们有 build_VS2017.targets 文件(如果你想在非 VS 2017 版本上使用它可能需要进行调整,至少我在从 2015 年迁移到 2017 年时做了一些事情):
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- This simple inline task displays "Hello, world!" -->
<UsingTask
TaskName="ReorderSqlProjFile_Inline"
TaskFactory="CodeTaskFactory"
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll" >
<ParameterGroup />
<Task>
<Reference Include="System.Xml"/>
<Reference Include="System.Core"/>
<Reference Include="System.Xml.Linq"/>
<Using Namespace="Microsoft.Build.Framework" />
<Using Namespace="Microsoft.Build.Utilities" />
<Using Namespace="System"/>
<Using Namespace="System.IO"/>
<Using Namespace="System.Text"/>
<Using Namespace="System.Linq"/>
<Using Namespace="System.Xml.Linq"/>
<Using Namespace="System.Collections.Generic"/>
<Code Type="Class" Language="cs">
<![CDATA[
using System.Linq;
public class ReorderSqlProjFile_Inline : Microsoft.Build.Utilities.Task
{
private string _projectFullPath = @"]]>$(MSBuildProjectFullPath)<![CDATA[";
public override bool Execute()
{
try
{
System.Xml.Linq.XDocument document = System.Xml.Linq.XDocument.Load(_projectFullPath, System.Xml.Linq.LoadOptions.PreserveWhitespace | System.Xml.Linq.LoadOptions.SetLineInfo);
System.Xml.Linq.XNamespace msBuildNamespace = document.Root.GetDefaultNamespace();
System.Xml.Linq.XName itemGroupName = System.Xml.Linq.XName.Get("ItemGroup", msBuildNamespace.NamespaceName);
var itemGroups = document.Root.Descendants(itemGroupName).ToArray();
var processedItemGroups = new System.Collections.Generic.List<System.Xml.Linq.XElement>();
CombineCompatibleItemGroups(itemGroups, processedItemGroups);
foreach (System.Xml.Linq.XElement itemGroup in processedItemGroups)
{
SortItemGroup(itemGroup);
}
var originalBytes = System.IO.File.ReadAllBytes(_projectFullPath);
byte[] newBytes = null;
using (var memoryStream = new System.IO.MemoryStream())
using (var textWriter = new System.IO.StreamWriter(memoryStream, System.Text.Encoding.UTF8))
{
document.Save(textWriter, System.Xml.Linq.SaveOptions.None);
newBytes = memoryStream.ToArray();
}
if (!AreEqual(originalBytes, newBytes))
{
Log.LogMessageFromText("=== RESULT: Included files in *.sqlproj need to be reordered. ===", Microsoft.Build.Framework.MessageImportance.High);
if (!new System.IO.FileInfo(_projectFullPath).IsReadOnly)
{
System.IO.File.WriteAllBytes(_projectFullPath, newBytes);
Log.LogMessageFromText("=== *.sqlproj has been overwritten. ===", Microsoft.Build.Framework.MessageImportance.High);
Log.LogMessageFromText("=== Visual Studio will ask to reload project. ===", Microsoft.Build.Framework.MessageImportance.High);
Log.LogMessageFromText("=== ===", Microsoft.Build.Framework.MessageImportance.High);
Log.LogMessageFromText("=============================================================================", Microsoft.Build.Framework.MessageImportance.High);
}
else
{
Log.LogMessageFromText("=== *.sqlproj is readonly. Cannot overwrite *.sqlproj file. ===", Microsoft.Build.Framework.MessageImportance.High);
Log.LogMessageFromText("=== ===", Microsoft.Build.Framework.MessageImportance.High);
Log.LogMessageFromText("=============================================================================", Microsoft.Build.Framework.MessageImportance.High);
}
}
else
{
Log.LogMessageFromText("=== RESULT: *.sqlproj is OK. ===", Microsoft.Build.Framework.MessageImportance.High);
Log.LogMessageFromText("=== ===", Microsoft.Build.Framework.MessageImportance.High);
Log.LogMessageFromText("=============================================================================", Microsoft.Build.Framework.MessageImportance.High);
}
return true;
}
catch (System.Exception ex)
{
Log.LogMessageFromText("=== RESULT: Exception occured trying to reorder *.sqlproj file. ===", Microsoft.Build.Framework.MessageImportance.High);
Log.LogMessageFromText("=== Exception:" + ex, Microsoft.Build.Framework.MessageImportance.High);
Log.LogMessageFromText("=== ===", Microsoft.Build.Framework.MessageImportance.High);
Log.LogMessageFromText("=============================================================================", Microsoft.Build.Framework.MessageImportance.High);
return true;
}
}
public bool AreEqual(byte[] left, byte[] right)
{
if (left == null)
{
return right == null;
}
if (right == null)
{
return false;
}
if (left.Length != right.Length)
{
return false;
}
for (int i = 0; i < left.Length; i++)
{
if (left[i] != right[i])
{
return false;
}
}
return true;
}
public void CombineCompatibleItemGroups(System.Xml.Linq.XElement[] itemGroups, System.Collections.Generic.List<System.Xml.Linq.XElement> processedItemGroups)
{
var itemTypeLookup = itemGroups.ToDictionary(i => i, i => GetItemTypesFromItemGroup(i));
foreach (var itemGroup in itemGroups)
{
if (!itemGroup.HasElements)
{
RemoveItemGroup(itemGroup);
continue;
}
var suitableExistingItemGroup = FindSuitableItemGroup(processedItemGroups, itemGroup, itemTypeLookup);
if (suitableExistingItemGroup != null)
{
ReplantAllItems(from: itemGroup, to: suitableExistingItemGroup);
RemoveItemGroup(itemGroup);
}
else
{
processedItemGroups.Add(itemGroup);
}
}
}
public void RemoveItemGroup(System.Xml.Linq.XElement itemGroup)
{
var leadingTrivia = itemGroup.PreviousNode;
if (leadingTrivia is System.Xml.Linq.XText)
{
leadingTrivia.Remove();
}
itemGroup.Remove();
}
public void ReplantAllItems(System.Xml.Linq.XElement from, System.Xml.Linq.XElement to)
{
if (to.LastNode is System.Xml.Linq.XText)
{
to.LastNode.Remove();
}
var fromNodes = from.Nodes().ToArray();
from.RemoveNodes();
foreach (var element in fromNodes)
{
to.Add(element);
}
}
public System.Xml.Linq.XElement FindSuitableItemGroup(
System.Collections.Generic.List<System.Xml.Linq.XElement> existingItemGroups,
System.Xml.Linq.XElement itemGroup,
System.Collections.Generic.Dictionary<System.Xml.Linq.XElement, System.Collections.Generic.HashSet<string>> itemTypeLookup)
{
foreach (var existing in existingItemGroups)
{
var itemTypesInExisting = itemTypeLookup[existing];
var itemTypesInCurrent = itemTypeLookup[itemGroup];
if (itemTypesInCurrent.IsSubsetOf(itemTypesInExisting) && AreItemGroupsMergeable(itemGroup, existing))
{
return existing;
}
}
return null;
}
public bool AreItemGroupsMergeable(System.Xml.Linq.XElement left, System.Xml.Linq.XElement right)
{
if (!AttributeMissingOrSame(left, right, "Label"))
{
return false;
}
if (!AttributeMissingOrSame(left, right, "Condition"))
{
return false;
}
return true;
}
public bool AttributeMissingOrSame(System.Xml.Linq.XElement left, System.Xml.Linq.XElement right, string attributeName)
{
var leftAttribute = left.Attribute(attributeName);
var rightAttribute = right.Attribute(attributeName);
if (leftAttribute == null && rightAttribute == null)
{
return true;
}
else if (leftAttribute != null && rightAttribute != null)
{
return leftAttribute.Value == rightAttribute.Value;
}
return false;
}
public System.Collections.Generic.HashSet<string> GetItemTypesFromItemGroup(System.Xml.Linq.XElement itemGroup)
{
var set = new System.Collections.Generic.HashSet<string>();
foreach (var item in itemGroup.Elements())
{
set.Add(item.Name.LocalName);
}
return set;
}
public void SortItemGroup(System.Xml.Linq.XElement itemGroup)
{
System.Collections.Generic.List<System.Xml.Linq.XElement> list = new System.Collections.Generic.List<System.Xml.Linq.XElement>();
foreach (System.Xml.Linq.XElement element in itemGroup.Elements())
list.Add(element);
var original = list.ToArray();
var sorted = original
.OrderBy(i => i.Name.LocalName)
.ThenBy(i => (i.Attribute("Include") ?? i.Attribute("Remove")).Value)
.ToArray();
for (int i = 0; i < original.Length; i++)
{
original[i].ReplaceWith(sorted[i]);
}
}
}
]]>
</Code>
</Task>
</UsingTask>
<Target Name="BeforeBuild">
<Message Text="=============================================================================" Importance="high" />
<Message Text="=================== ===================" Importance="high" />
<Message Text="=================== RUNNING PREBIULD SCRIPT ===================" Importance="high" />
<Message Text="=== ===" Importance="high" />
<Message Text="=== This script will order included files in *.sqlproj alphabetically ===" Importance="high" />
<Message Text="=== This is done to fix issues during merge process. ===" Importance="high" />
<Message Text="=== ===" Importance="high" />
<Message Text="=== FYI: To disable this script comment next line in *.sqlproj file: ===" Importance="high" />
<Message Text="=== <Import Project="build_VS2017.targets" /> ===" Importance="high" />
<Message Text="=== ===" Importance="high" />
<Message Text="=== ===" Importance="high" />
<Message Text="=== ===" Importance="high" />
<Message Text="=============================================================================" Importance="high" />
<ReorderSqlProjFile_Inline />
</Target>
</Project>
然后在项目文件中,在 </Project>
之前添加以下条目:
...
<Import Project="build_VS2017.targets" Condition="'$(Configuration)'=='Debug'" />
</Project>
关于visual-studio - .sqlproj 文件的版本控制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59990934/
我想根据我使用的 visual studio 版本编译不同的东西,比如 #if VISUAL_STUDIO_VERSION > 2015 eventH?.Invoke(this, EventArgs.
在 Visual Studio 2010 中调试并将鼠标悬停在变量名称上时,我可以选择使用 3 种不同的内置可视化工具:文本、XML 和 HTML。 这是我所指的示例: 由于我越来越多地使用基于 JS
我将可视化编程语言理解为允许程序员在屏幕上操作图形(而不是文本)对象以构建功能的语言。 我在 C#、VB 等中看到的最接近的东西是 RAD 控件,但这只是组成 UI 和最简单的功能——甚至与语言本身无
我目前正在使用 Visual Studio 2015 来编程 ASP.NET Core 应用程序。我对安装 Visual Studio 2017 有以下疑问: 什么被认为是最佳实践和/或最干净的方法?
尝试从扩展和更新获取 Visual Studio 扩展时,出现以下错误:- 向 visualstudiogallery.msdn.microsoft.com/Services/VStudio/Exte
我已经开发了Windows服务,并且该服务正在我的帐户下在本地计算机上运行。当我尝试通过在Visual Studio 2008中将其作为一个过程附加该服务来调试该服务时,我得到“无法附加到该过程。 V
作为标准安装的一部分,Visual Studio Code 带有一个名为“Monokai Dimmed”的颜色主题。 有没有办法将它移植到 Visual Studio 2015?我检查了社区主题( h
Visual Studio Community Edition是否可以使用Visual Studio Online帐户上的存储库? 我一直为包含在Online帐户中的Visual Studio Onl
我正在使用文本可视化工具在 Visual Studio 中调试字符串变量。然而,似乎字符串中间的大部分不见了。这背后的原因是什么? 最佳答案 Visual Studio 中的 Text Visuali
我正在开始一个涉及使用多个 SDK 的新项目,包括: 英特尔凌动开发者 SDK 文本转语音 SDK(建议?) 某种网络摄像头和增强现实支持(建议?) 我目前有 2008,但我也可以安装 2010。是否
我想知道,如果我发送一个解决方案文件夹(它是用 visual studio C# 编写的),您可以在 visual studio for mac 中打开解决方案吗? 在visual studio 20
有没有办法在 Visual Studio Code 和 Visual Studio 中设置相同的快捷方式(而不必每次都手动更改它们)? 例如,我在 Visual Studio Code 中经常使用 A
我无法启用 实时可视化树 在 Visual Studio 2017 用于 UWP 应用程序 (C#)。这个工具在 VS2015 上工作,但在 VS2017 中从来没有为我工作过。它对我的 WPF 项目
我刚开始了解 Visual Studio Code。我想知道,我可以将 Visual Studio 替换为所有 .NET 开发相关的工作吗? 我可以节省 Visual Studio 许可的成本吗? V
我安装了具有有效许可证(Visual Studio 订阅)的 Visual Studio 2019 企业版(VS 2019 16.1.4),它运行良好。 突然之间,当我尝试打开项目或项目中的任何文件时
Visual Studio 2015 Pro 提供以下 错误 : error BC36716: Visual Basic 9.0 does not support implicit line cont
我正在我的 PC 中使用 .net Framework 2.0 和 Visual C#(Microsoft Visual Studio 2008)开发 Windows 应用程序。 完成我的项目后,我必
有什么方法可以在启动 VS 时禁用 VA X 并仅在需要时将其重新打开?因为它会导致一些滞后。我似乎在 VS 的选项或 VA 的选项中都找不到该选项。 最佳答案 持shift在 Visual Stud
我可以将 Visual Studio 命令提示符 与免费的 Visual C# Express 一起使用吗? Visual Studio 命令提示符 被引用 here : Run 'Visual St
这很容易成为 Visual Studio 历史上最烦人的“功能”之一,我不明白它为什么存在 -- 曾经 . 为什么 CodePlex 项目需要关心我使用的是什么版本的 Visual Studio? 在
我是一名优秀的程序员,十分优秀!