Dbset 作为实体框架中的 hashset

时间:2021-07-20 16:49:36

标签: c# .net-core entity-framework-core

我需要将数据库中表中的数据与基于第三方来源的某些逻辑的数据合并。我通过 hashset 实现了这个逻辑,为此我重载了实体的 GetHashCode 和 Equals 方法。现在不明白如何通过DbSet将工作结果保存在数据库中,进行后续数据加载和后续合并(合并/补充的任务是周期性的)

目录非常庞大,因此使用 hashset 可以加快进程。

    class Program
    {
        private class DummyDbContext { public void SaveChangesAsync() { }}

        static void Main(string[] args)
        {
            var dbContext = new DummyDbContext(); // TODO: Get from DI

            // TODO: I don't know how to do it yet with HashSets
            var currentFactories = LoadCurrentFactoriesFromDb(dbContext);
            var currentProducts = LoadCurrentProductsFromDb(dbContext);

            var thirdPartyData = GetThirdPartyData();

            foreach (var data in thirdPartyData)
            {
                /*
                 In reality, the logic is more complicated, because some data transformation is required.
                 Some data may be missing. That is why comparing two objects is not quite easy (see the method Product.Equals)
                 */
                var factory = new Factory(data.otherFactory.Name); 
                var product = new Product(data.otherProduct.Property1, data.otherProduct.Property2, factory);

                if (currentFactories.TryGetValue(factory, out var existedFactory))
                    factory = existedFactory;
                else
                    currentFactories.Add(factory);

                if (currentProducts.TryGetValue(product, out var existedProduct))
                {
                    if (!existedProduct.Factory.Equals(factory))
                        throw new InvalidOperationException(); // TODO:
                    product = existedProduct;
                    factory.Products.Add(product); // TODO:
                }
                else
                    currentProducts.Add(product);
            }

            // **how to implement the saving of combined directories, in hashsets, in the database ?**
            dbContext.SaveChangesAsync();
        }

        private static IEnumerable<(ThirdPartyFactory otherFactory, ThirdPartyProduct otherProduct)> GetThirdPartyData()
        {
            return new (ThirdPartyFactory otherFactory, ThirdPartyProduct otherProduct)[]
            {
                ( new ThirdPartyFactory () {Name = "SomeFactory"}, new ThirdPartyProduct() {Property1 = "ProductName1"}),
                ( new ThirdPartyFactory () {Name = "SomeFactory"}, new ThirdPartyProduct() {Property1 = "ProductName2"}),
                ( new ThirdPartyFactory () {Name = "SomeFactory"}, new ThirdPartyProduct() {Property2 = "Property1"})
            };
        }

        private static HashSet<Factory> LoadCurrentFactoriesFromDb(DummyDbContext context)
        {
            // DbContext.DbSet<Factory>.GetAll()
            return new HashSet<Factory>();
        }

        private static HashSet<Product> LoadCurrentProductsFromDb(DummyDbContext context)
        {
            // DbContext.DbSet<Product>.GetAll()
            return new HashSet<Product>();
        }
    }

    public class Product
    {
        public Product(string property1, string property2, Factory factory)
        {
            Property1 = property1;
            Property2 = property2;
            Factory = factory;
        }

        public long Id { get; set; }

        public string Property1 { get; }
        public string Property2 { get; }

        public Factory Factory { get; }

        public override bool Equals(object? obj)
        {
            if (obj == null)
                return false;
            var product = (Product) obj;

            return (string.IsNullOrWhiteSpace(Property1) && string.IsNullOrWhiteSpace(product.Property1) 
                    || string.CompareOrdinal(this.Property1, product.Property1) == 0)

                   && (string.IsNullOrWhiteSpace(Property2) && string.IsNullOrWhiteSpace(product.Property2)
                       || string.CompareOrdinal(this.Property2, product.Property2) == 0);
        }

        public override int GetHashCode()
        {
            return HashCode.Combine(Property1, Property2).GetHashCode();
        }
    }

    public class Factory
    {
        public Factory(string name)
        {
            Name = name;
        }

        public long Id { get; set; }
        public string Name { get; }

        public HashSet<Product> Products { get; set; }
    }

    public class ThirdPartyProduct
    {
        public string Property1 { get; set; }
        public string Property2 { get; set; }
    }

    public class ThirdPartyFactory
    {
        public string Name { get; set; }
    }

是否可以实现这一点?或者我是否需要将数据从 DbSet 转换为 HashSet 然后再返回?但是在这种转换过程中,我不会丢失上下文中实体的信息吗?

0 个答案:

没有答案