How to automate setting ConcurrencyMode=Fixed on all RowVersion columns?

前端 未结 7 1391
攒了一身酷
攒了一身酷 2021-01-04 13:03

EF defaults to no concurrency control (last write wins) which allows lost updates. Enforcing optimistic concurrency checks can explicitly be configured by setting Concurrenc

相关标签:
7条回答
  • 2021-01-04 13:10

    I got bored with setting ConcurrencyMode manually, so I wrote a tiny utility to automate it. You can either use it to set the mode for certain types (timestamp/rowversion) or for column names matching certain regex patterns.

    http://blog.wezeku.com/2014/04/28/fixefconcurrencymodes/

    https://github.com/wezeku/FixEFConcurrencyModes

    0 讨论(0)
  • 2021-01-04 13:11

    In EF6 the designer will set ConcurrencyMode=Fixed on rowversion columns when creating a model from the database.See Designer: Automate setting ConcurrencyMode=Fixed on rowversion columns. Until then we will have to do this manually.

    0 讨论(0)
  • 2021-01-04 13:11

    This is Mohamed Cassim answer but it's working for EF6

    static Dictionary<string, string> replacements = new Dictionary<string, string>()
        {
            { "<Property Name=\"RowVersion\" Type=\"Binary\" Nullable=\"false\" MaxLength=\"8\" FixedLength=\"true\" annotation:StoreGeneratedPattern=\"Computed\" />",
              "<Property Name=\"RowVersion\" Type=\"Binary\" Nullable=\"false\" MaxLength=\"8\" FixedLength=\"true\" annotation:StoreGeneratedPattern=\"Computed\" ConcurrencyMode=\"Fixed\" />"},
    
            { "<Property Name=\"rowversion\" Type=\"Binary\" Nullable=\"false\" MaxLength=\"8\" FixedLength=\"true\" annotation:StoreGeneratedPattern=\"Computed\" />",
              "<Property Name=\"rowversion\" Type=\"Binary\" Nullable=\"false\" MaxLength=\"8\" FixedLength=\"true\" annotation:StoreGeneratedPattern=\"Computed\" ConcurrencyMode=\"Fixed\" />"},
    
            { "<Property Name=\"RowVer\" Type=\"Binary\" Nullable=\"false\" MaxLength=\"8\" FixedLength=\"true\" annotation:StoreGeneratedPattern=\"Computed\" />",
              "<Property Name=\"RowVer\" Type=\"Binary\" Nullable=\"false\" MaxLength=\"8\" FixedLength=\"true\" annotation:StoreGeneratedPattern=\"Computed\" ConcurrencyMode=\"Fixed\" />"},
    
            { "<Property Name=\"rowver\" Type=\"Binary\" Nullable=\"false\" MaxLength=\"8\" FixedLength=\"true\" annotation:StoreGeneratedPattern=\"Computed\" />",
              "<Property Name=\"rowver\" Type=\"Binary\" Nullable=\"false\" MaxLength=\"8\" FixedLength=\"true\" annotation:StoreGeneratedPattern=\"Computed\" ConcurrencyMode=\"Fixed\" />"},
    
            { "<Property Name=\"RowVersion\" Type=\"Binary\" MaxLength=\"8\" FixedLength=\"true\" annotation:StoreGeneratedPattern=\"Computed\" />",
              "<Property Name=\"RowVersion\" Type=\"Binary\" MaxLength=\"8\" FixedLength=\"true\" annotation:StoreGeneratedPattern=\"Computed\" ConcurrencyMode=\"Fixed\" />"},
    
            { "<Property Name=\"rowversion\" Type=\"Binary\" MaxLength=\"8\" FixedLength=\"true\" annotation:StoreGeneratedPattern=\"Computed\" />",
              "<Property Name=\"rowversion\" Type=\"Binary\" MaxLength=\"8\" FixedLength=\"true\" annotation:StoreGeneratedPattern=\"Computed\" ConcurrencyMode=\"Fixed\" />"},
    
            { "<Property Name=\"RowVer\" Type=\"Binary\" MaxLength=\"8\" FixedLength=\"true\" annotation:StoreGeneratedPattern=\"Computed\" />",
              "<Property Name=\"RowVer\" Type=\"Binary\" MaxLength=\"8\" FixedLength=\"true\" annotation:StoreGeneratedPattern=\"Computed\" ConcurrencyMode=\"Fixed\" />"},
    
            { "<Property Name=\"rowver\" Type=\"Binary\" MaxLength=\"8\" FixedLength=\"true\" annotation:StoreGeneratedPattern=\"Computed\" />",
              "<Property Name=\"rowver\" Type=\"Binary\" MaxLength=\"8\" FixedLength=\"true\" annotation:StoreGeneratedPattern=\"Computed\" ConcurrencyMode=\"Fixed\" />"},
        };
    
        static void Main(string[] args)
        {
            // find all .edmx
            string directoryPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
            foreach (var file in Directory.GetFiles(directoryPath))
            {
                // only edmx
                if (!file.EndsWith(".edmx"))
                    continue;
    
                Console.WriteLine("File Name Found : " + file);
    
                // read file
                var fileContents = File.ReadAllText(file);
    
                // replace lines
                foreach (var item in replacements)
                    fileContents = fileContents.Replace(item.Key, item.Value);
    
                // overwite file
                File.WriteAllText(file, fileContents);
    
                Console.WriteLine("\nFile : " + file + "Changed");
            }
        }
    
    0 讨论(0)
  • 2021-01-04 13:12

    When you have added ConcurrencyMode=Fixed once in your edmx file, then afterwards every time you update your model, before checkin in code (assuming you have some version control life TFS setup), compare with the latest version and merge changes accordingly. This way you dont have to update every single line manually. Not the best way, but better than doing it manually atleast.

    0 讨论(0)
  • 2021-01-04 13:16

    Seems like this Feature is not going to be around for EF 5 or EF 6.

    I whipped up a quick console app to update the edmx after generating DB First.

    Just drop the file in the same directory of your edmx file and run after every regeneration.

    Will work for any of the following columns:

    RowVersion    timestamp    NOT NULL
    rowversion    timestamp    NOT NULL
    RowVer        timestamp    NOT NULL
    rowver        timestamp    NOT NULL
    

    You can get the console app here https://dl.dropbox.com/u/3576345/EFConcurrencyFixed.exe

    or use this piece of code in your own console app.

    class Program
    {
        static Dictionary<string, string> replacements = new Dictionary<string, string>()
        {
            { "<Property Type=\"Binary\" Name=\"RowVersion\" Nullable=\"false\" MaxLength=\"8\" FixedLength=\"true\" annotation:StoreGeneratedPattern=\"Computed\" />",
              "<Property Type=\"Binary\" Name=\"RowVersion\" Nullable=\"false\" MaxLength=\"8\" FixedLength=\"true\" annotation:StoreGeneratedPattern=\"Computed\" ConcurrencyMode=\"Fixed\" />"},
    
            { "<Property Type=\"Binary\" Name=\"rowversion\" Nullable=\"false\" MaxLength=\"8\" FixedLength=\"true\" annotation:StoreGeneratedPattern=\"Computed\" />",
              "<Property Type=\"Binary\" Name=\"rowversion\" Nullable=\"false\" MaxLength=\"8\" FixedLength=\"true\" annotation:StoreGeneratedPattern=\"Computed\" ConcurrencyMode=\"Fixed\" />"},
    
            { "<Property Type=\"Binary\" Name=\"RowVer\" Nullable=\"false\" MaxLength=\"8\" FixedLength=\"true\" annotation:StoreGeneratedPattern=\"Computed\" />",
              "<Property Type=\"Binary\" Name=\"RowVer\" Nullable=\"false\" MaxLength=\"8\" FixedLength=\"true\" annotation:StoreGeneratedPattern=\"Computed\" ConcurrencyMode=\"Fixed\" />"},
    
            { "<Property Type=\"Binary\" Name=\"rowver\" Nullable=\"false\" MaxLength=\"8\" FixedLength=\"true\" annotation:StoreGeneratedPattern=\"Computed\" />",
              "<Property Type=\"Binary\" Name=\"rowver\" Nullable=\"false\" MaxLength=\"8\" FixedLength=\"true\" annotation:StoreGeneratedPattern=\"Computed\" ConcurrencyMode=\"Fixed\" />"},
        };
    
        static void Main(string[] args)
        {
            // find all .edmx
            string directoryPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
            foreach (var file in Directory.GetFiles(directoryPath))
            {
                // only edmx
                if (!file.EndsWith(".edmx"))
                    continue;
    
                // read file
                var fileContents = System.IO.File.ReadAllText(file);
    
                // replace lines
                foreach (var item in replacements)
                    fileContents = fileContents.Replace(item.Key, item.Value);
    
                // overwite file
                System.IO.File.WriteAllText(file, fileContents);
            }
        }
    }
    
    0 讨论(0)
  • 2021-01-04 13:17

    I have not done it myself (yet, but will probably need to soon), but it should be possible to change the tool used for generating code from the .edmx.

    Here is an article explaining it for VS2008. I guess the process will be about the same for VS2010 and VS2012.

    I'm not currently sure, though, whether this will make it possible to muck around with the ConcurrencyMode in any way.

    0 讨论(0)
提交回复
热议问题