msawczyn/EFDesigner2022

Prevent EFModelFileManager.ttinclude from deleting previously generated code by other model

Sancho-Lee opened this issue · 0 comments

EFDesigner v4.2.1.3

Phenomenon:
If there are more than one model in a project, files created in other models are deleted when code is generated for a specific model.

In EFModelFileManager.ttinclude,

            private void ProjectSync(IEnumerable<string> keepFileNames)
            {
               Dictionary<ProjectItem, List<string>> current = GetCurrentState();

               string[] fileNames = keepFileNames as string[] ?? keepFileNames.ToArray();
               Dictionary<ProjectItem, List<string>> target = GetTargetState(fileNames);
               List<string> allTargetFiles = target.Keys.SelectMany(k => target[k]).ToList();

               List<string> existingFiles = new List<string>();

               foreach (ProjectItem parentItem in current.Keys.ToList())
               {
                  foreach (string filename in current[parentItem])
                  {
                     if (!allTargetFiles.Contains(filename) && !fileNames.Contains(filename)) // here
                        dte.Solution.FindProjectItem(filename)?.Delete();
                     else
                        existingFiles.Add(filename);
                  }
               }

               // just to be safe
               existingFiles = existingFiles.Distinct().ToList();

               foreach (ProjectItem parentItem in target.Keys.ToList())
               {
                  foreach (string filename in target[parentItem].Except(existingFiles).ToList())
                     parentItem.ProjectItems.AddFromFile(filename);
               }
            }

Suggestion:
I have solved this issue by deleting files if the specified file is in the directory of target files

I copied the EFModelFileManager.ttinclude file to model location and added a function to determine for deleting like below(code not optimized)

        bool shouldDelete(string[] targetFileNames, string fileName)
	{
				Dictionary<string, string> directories = new Dictionary<string, string>();
				foreach (string targetFilename in targetFileNames)
				{
					string? directory = Path.GetDirectoryName(targetFilename);
					if (directory != null)
					{
						if (!directories.ContainsKey(directory))
							directories.Add(directory, targetFilename);
					}
				}
				return directories.ContainsKey(Path.GetDirectoryName(fileName));
	}

and then,

            private void ProjectSync(IEnumerable<string> keepFileNames)
            {
               Dictionary<ProjectItem, List<string>> current = GetCurrentState();

               string[] fileNames = keepFileNames as string[] ?? keepFileNames.ToArray();
               Dictionary<ProjectItem, List<string>> target = GetTargetState(fileNames);
               List<string> allTargetFiles = target.Keys.SelectMany(k => target[k]).ToList();

               List<string> existingFiles = new List<string>();

               foreach (ProjectItem parentItem in current.Keys.ToList())
               {
                  foreach (string filename in current[parentItem])
                  {
                     if (!allTargetFiles.Contains(filename) && shouldDelete(fileNames, filename)) // changed
                        dte.Solution.FindProjectItem(filename)?.Delete();
                     else
                        existingFiles.Add(filename);
                  }
               }

               // just to be safe
               existingFiles = existingFiles.Distinct().ToList();

               foreach (ProjectItem parentItem in target.Keys.ToList())
               {
                  foreach (string filename in target[parentItem].Except(existingFiles).ToList())
                     parentItem.ProjectItems.AddFromFile(filename);
               }
            }

This worked for me.
Hope this helps.