繁体   English   中英

使用 MVVM 创建具有现有外部属性的 EF Core 实体

[英]Creating an EF Core entity with an existing foreign property with MVVM

我将 MVVM 与 EF Core 一起使用。 我有一个实体,该实体具有预先播种到数据库的外部属性,如下所示:

public class STOCK : EntityBase
{
    public string TEXT {get;set;}
    public decimal AMOUNT {get;set;}

    private TAX SALESTAX {get;set;}
    [ForeignKey("SALESTAX")]
    public int SALESTAX_ID {get;set;}

    private TAX SPECIALTAX {get;set}
    [ForeignKey("SPECIALTAX")]
    public int SPECIALTAX_ID {get;set;}
}

public class TAX
{
    public int TAXCODE {get;set;}
    public string NAME {get;set;}
    
    public ICollection<STOCK> STOCK_TAX {get;set;}
    public ICollection<STOCK> STOCK_SPECIAL {get;set}
}

public class EntityBase, INotifyPropertyChanged
{
    public int ID {get;set;}
    //The interface is fully implemented here. Removed for brevity.
}

在我的 ViewModel 上,我同时注入了StockDataServiceTaxDataService ,如下所示:

public class StockDataService : IStockDataService
{
    private readonly MyDbContextFactory _factory;
    
    public StockDataService(MyDbContextFactory factory)
    {
        _factory = factory;
    }

    public async Task<STOCK> Create(STOCK entity)
    {
        using MyDbContext context = _factory.CreateDbContext();
        STOCK createdResult = await context.STOCKs.AddAsync(entity);
        return createdResult;
    } //Other CRUD methods are implemented as well, but removed for brevity.
}

public class TaxDataService : ITaxDataService
{
    private readonly MyDbContextFactory _factory;
    
    public TaxDataService(MyDbContextFactory factory)
    {
        _factory = factory;
    }

    public async Task<TAX> GetAll()
    {
        using MyDbContext context = _factory.CreateDbContext();
        return await context.TAXs.ToListAsync();
    }//Ditto
}

我的观点有一个 combobox 如下:

<ComboBox ItemsSource="{Binding TAXES}"
          SelectedValue="{Binding SALESTAX, Mode=TwoWay, UpdateSourceTrigger=Default}"  
          SelectedItem="{Binding SALESTAX}">
    <ComboBox.ItemsPanel>
        <ItemsPanelTemplate>
            <VirtualizingStackPanel/>
        </ItemsPanelTemplate>
    </ComboBox.ItemsPanel>
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal" Margin="0">
                <Border Padding="0,0,2,0" BorderThickness="1" BorderBrush="LightGray">
                    <TextBlock>
                <Run Text="{Binding TAXCODE}"/>
                    </TextBlock>
                </Border>
                <Border Padding="2,0,0,0" BorderThickness="1" BorderBrush="LightGray">
                    <TextBlock>
                <Run Text="{Binding TEXT}"/>
                    </TextBlock>
                </Border>
            </StackPanel>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

我的视图模型如下:

public class StockCrudViewModel
{
    private readonly IStockDataService _stockDataService;
    private readonly ITaxDataService _taxDataService;
    public STOCK CurrentStock {get;set;}

    public ICollection<TAX> TAXES {get;set;}

    public StockCrudViewModel(IStockDataService stockDataService, ITaxDataService taxDataService)
    {
        _stockDataService = stockDataService;
        _taxDataService = taxDataService;

        FillTaxesList();
    }

    private async void FillTaxesList()
    {
        TAXES = new List<TAX>(await _taxDataService.GetAll());
    }

“保存”命令如下:

await _stockDataService.Create(_stockCrudViewModel.STOCK);
//Both the data service as well as the scoped view model are passed via dependency injection to the command.

编辑:我的DbContextHostBuilder如下:

host.ConfigureServices((context, myServices) =>
     {
         string connString = context.Configuration.GetConnectionString("default");
         Action<DbContextOptionsBuilder> configureDbContext = c => { c.UseMySql(connString); c.EnableSensitiveDataLogging(); };
         myServices.AddSingleton<MyDbContextFactory>(new MyDbContextFactory(configureDbContext));
         myServices.AddDbContext<MyDbContext>(configureDbContext);
     });

现在,我明白为什么这样做会引发“尝试创建重复条目”异常,因为通过绑定设置SALESTAX属性将使用来自不同MyDbContext实例的TAX ,因此 EF Core 无法相应地跟踪它。 但是,由于我使用的是AddDbContext并传递工厂而不是上下文本身,因此每次调用数据服务方法之一时都会实例化一个新的上下文,我不确定如何让 EF Core 知道已经存在应使用的现有TAX条目。

根据如何使用已存在于 EF 核心中的子实体保存实体? ,他们建议使用用于创建新条目的相同上下文来获取现有条目。 但是如果我的实体有五个或更多的外国财产,那不会影响业绩吗? 还是我在规划 MVVM 架构时搞砸了?

还是我在规划 MVVM 架构时搞砸了?

是的。 MVVM 中 DbContext 的正确 scope 和生命周期位于 ViewModel 上。

这为您提供了 ViewModel 的单个 ChangeTracker 和工作单元,并使用Local Data启用数据绑定到加载的实体,这是一个 ObservableCollection。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM